RNG

thoughts on software development and everything else

Git tips: subtree

2019-06-13

The problem

Here’s the situation. You have a big project in git. It has many modules. Over time these modules get more complex and become libraries in their own right. So you want to take that library and make it into its own project. And obviously, you want that libary in source control.

You could just copy the folder over to a new blank git repository:

mkdir my-cool-lib
git init my-cool-lib
mv my-huge-project/lib/cool my-cool-lib

But then you’d lose all that useful git history - all the changes, bugfixes and most importantly the reasons for them. You wouldn’t be able to roll back the libary to a particular point in time, or undo a granual change.

You could copy the whole huge project and delete everything besides your library.

cp my-huge-project project-copy
rm my-huge-project/folder1 my-huge-project/folder2...

But then you would have all this git history of non-library files cluttering things up.

Turns out, there is an easy way to copy the library out and only get the git history for the files in that folder!

The solution

That easy way is git subtree! With that, you can turn the cool folder into its own separate git repository. Then it’s easy to move that to a new physical location.

cd my-huge-project/lib
git subtree split -P cool -b mcl

This gives you a branch called mcl that only has the commits for the cool folder.

Make your new folder somewhere else and pull the mcl branch into it.

cd ~
mkdir my-cool-lib
cd my-cool-lib
git init
git pull my-huge-project mcl

You now have a separate git repo with just your libary code and all its history. Check it out with git log. If you want to link it to a remote repository, simply create it on your VCS (I use Gitlab), and add it:

git remote add origin git@gitlab.com:ronniegane/my-cool-lib
git push origin -u master

That’s all there is to it!

Many thanks to AJ ONeal who I learned this from on StackOverflow.