There are times when submodules are not adequate for the task at hand. For example, blending multiple repositories together into one single repository while still maintaining the history of each repository. To do this, the subtree merge strategy is a better solution.

Setting up and doing the first merge

For this example, we'll make an empty "parent" repository and merge some other repositories into it as subpaths.

First, set up an empty repository for our example:

mkdir test
cd test
git init
# Initialized empty Git repository in /Users/tekkub/tmp/test/.git/
touch .gitignore
git add .gitignore
git commit -m "initial commit"
# [master (root-commit) 3146c2a] initial commit
#  0 files changed, 0 insertions(+), 0 deletions(-)
#  create mode 100644 .gitignore

Now, we'll subtree-merge the repository teknologic/Cork into the repository at cork/

git remote add -f cork git://github.com/TekNoLogic/Cork.git
# Updating cork
# warning: no common commits
# remote: Counting objects: 1732, done.
# remote: Compressing objects: 100% (750/750), done.
# remote: Total 1732 (delta 1086), reused 1558 (delta 967)
# Receiving objects: 100% (1732/1732), 528.19 KiB | 621 KiB/s, done.
# Resolving deltas: 100% (1086/1086), done.
# From git://github.com/tekkub/cork
#  * [new branch]      lastbuffed -> cork/lastbuffed
#  * [new branch]      lock_n_mount -> cork/lock_n_mount
#  * [new branch]      master     -> cork/master
#  * [new branch]      nothing_to_see_here -> cork/nothing_to_see_here

git merge -s ours --no-commit cork/master
# Automatic merge went well; stopped before committing as requested

git read-tree --prefix=cork/ -u cork/master
git commit -m "Subtree merged in cork"
# [master fe0ca25] Subtree merged in cork

Next, we'll merge in teknologic/Panda into the path panda/

git remote add -f panda git://github.com/TekNoLogic/Panda.git
# Updating panda
# warning: no common commits
# remote: Counting objects: 974, done.
# remote: Compressing objects: 100% (722/722), done.
# remote: Total 974 (delta 616), reused 399 (delta 251)
# Receiving objects: 100% (974/974), 189.56 KiB, done.
# Resolving deltas: 100% (616/616), done.
# From git://github.com/tekkub/panda
#  * [new branch]      master     -> panda/master
#  * [new branch]      transmute  -> panda/transmute

git merge -s ours --no-commit panda/master
# Automatic merge went well; stopped before committing as requested

git read-tree --prefix=panda/ -u panda/master
git commit -m "Subtree merged in panda"
# [master 726a2cd] Subtree merged in panda

Finally, we're going to merge the subpath modules/ from tekkub/cork into cork2/

git merge -s ours --no-commit cork/master
# Automatic merge went well; stopped before committing as requested

git read-tree --prefix=cork2/ -u cork/master:modules
git commit -m "Subtree merged in cork/modules"
# [master f240057] Subtree merged in cork/modules

Pulling in changes

If the merged repository changes in the future, you can pull in its changes by simply using the -s subtree flag:

git pull -s subtree panda master

Tip: If you create a fresh clone of the repository in the future, the remotes you have added (cork, panda, etc.) will not be created for you. You will have to add them again using the git remote add command described earlier.

Resources