Name Last Update
my_lib Loading commit data...
README.md Loading commit data...

README.md

This is the parent that uses "git subtree".

Here's how you can re-trace the demo given at utviklerlunsj.

First, make yourself a directory and clone the repository into it:

git clone git@source.uit.no:lars.tiede/lunsjdemo_parent_with_subtree.git .

Now reset your working copy of this repository to the commit right before we added the subtree:

git reset --hard 8ae28dc5401ed9f4227c3a5514dc3a82221fdb90

Okay, now there shouldn't be any my_lib. Let's make ourselves a branch in order to not mess up the master branch:

git checkout -b YOU_CHOOSE

Now add my_lib as a subtree:

git log # just our boring history so far
git subtree add --prefix my_lib git@source.uit.no:lars.tiede/lunsjdemo_my_lib.git master
git status # everything has already been committed, no changes reported
git log # wow! Lots of stuff here all of a sudden

We can inspect what git actually did:

git show # all changes in last commit, note that git has the contents of my_lib (unlike when you use submodules)

You'll find that in the directory 'my_lib', you are still in the same repository (unlike when you use submodules):

git remote -v # shows that origin is "parent_with_subtree"
cd my_lib
git remote -v # shows that origin is "parent_with_subtree"
cd ..

Now do some random change in my_lib and commit and push it. You will see that the files have only changed in your repository, not my_lib's.

# change something in my\_lib. Then:
git add my_lib
git commit -m "did some changes in my_lib"
git push --set-upstream origin YOUR_BRANCH_NAME

For good measure, do some change in parent's files and commit and push that as well.

Let's assume that there are changes in the master branch, and you want to rebase your branch on master. This is what many people do very often.

git rebase master

Ouch. This is what happens:

First, rewinding head to replay your work on top of it...
Applying: [my_lib] first commit
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging README.md
CONFLICT (add/add): Merge conflict in README.md
Failed to merge in the changes.
Patch failed at 0001 [my_lib] first commit

The rebase failed instantly. What's worse is that there is no way to fix it. When you add a subtree, you can no longer rebase the branch you were working on. So let's bail out of this:

git rebase --abort

All changes you made to my_lib so far only live in your repository. Also, all changes to my_lib that might be available in my_libs origin are not automatically pulled at any time to your repository. Here is how you pull from, and push to my_lib's origin. Pull like this:

git subtree pull --prefix my_lib git@source.uit.no:lars.tiede/lunsjdemo_my_lib.git master

And push like this:

git subtree push --prefix my_lib git@source.uit.no:lars.tiede/lunsjdemo_my_lib.git master

You'll notice the longer-than-usual output. This is because git actually has to go through your repo's commit history and splice out all the commits that changed something in my_lib, extract the changes to my_lib, then make commits to my_lib based on those changes.

That's basically it, now you know how submodules work, and what their major caveat is. Delete your branch now so that there is no pollution on source.uit.no:

git push origin --delete YOUR_BRANCH_NAME