If you don’t have, imagine:
- You have got two applications built on Symfony2.
- Both of those applications are deployed on cloudControl.
- Both applications share one or more bundles you have written.
- All repositories are closed-source (Yes, those exist!).
- We got our first application on the remote repository
- We have another application on the remote repository
- We have the shared bundle on the remote repository
- The shared bundle will be put on the
As you can see, if you add the shared bundle to both repositories as
git submodule a deploy on
cloudControl would fail, as the deploying server cannot access the remote of the submodule.
That’s why you could make use of
git-subtree to share the code on both repositories and thus having it accessible on
Add the shared bundle
We will add the shared bundle on the first application
application-a as a subtree. There are only four steps required to make it work.
Configure the remote
The first step is registering the remote of the shared bundle on the repository of
This is done by issuing
git remote add -f shared-bundle firstname.lastname@example.org:shared-bundle.git.
The command will add a new remote (like
upstream) with the name
shared-bundle and the given repository.
-f option tells git to do a
fetch right away, so the local repository is up-to-date.
Merge the bundle
Now that git knows about the remote and therefore all of its content we proceed by actually applying the code,
git merge -s ours --no-commit shared-bundle/master.
This tells git to
merge the branch
master of the
shared-bundle into the
The merge strategy in use
ours ensures no files will be actually added now.
--no-commit option stops right before the merge commit would be created.
Now that the commits of the
shared-bundle/master are available, we are good to read the tree of the branch into the tree of
This is done by issuing
git read-tree --prefix=src/Acme/SharedBundle/ -u shared-bundle/master.
Now the tree of the shared bundle is available in the index of
It appears as a branch that has no parent in the current tree, which is correct.
The last required step is the actual commit of the staging area (the subtree):
Updating the bundle
After changing the
shared-bundle you only need to issue
git pull -s subtree shared-bundle master.
This will apply the changes and a merge commit will be created. If you don’t want an automatically created merge commit, add the
--no-commit option again.
Let’s take a look at the history of this subtree merge on
* 66815de - (HEAD, master) Merge branch 'master' of email@example.com:shared-bundle.git into master |\ | * 25f6757 - (shared-bundle/master) add empty README * | bcd30d9 - Merge remote-tracking branch 'shared-bundle/master' into master |\ \ | |/ | * 6dee0ac - add empty SharedBundle * 938473b - a commit before adding the subtree
As you can see, the tree of
6dee0ac (the first commit in
shared-bundle/master) has no parent in the
bcd30d9 is the result of the
git commit after
git read-tree which merged both trees (
6dee0ac under the prefix directory and
25f6757 is a commit in
shared-bundle/master which is merged by the
66815de commit using