Git Subtrees
Git subtrees are an alternative to submodules. Some developers prefer them because it’s faster to clone a project and get the shared code. Subtree is a more recent addition to Git.
Subtrees allow you to include another repository as a subdirectory in a project. Unlike Submodules, Subtrees don’t create configuration files or require multiple steps to initialize and fetch the included repository’s contents.
And, similar to submodules, a subtree can be altered via commits.
Adding a Subtree #
To add a subtree we use the special subtree commands. First, we add the repository:
$ git subtree add --prefix my-subdirectory
http://mysite.com/my_other_project.git master --squash
In the above example we are adding the external repository as a subtree in the my-subdirectory
directory. We are requesting the master
branch and using the --squash
option to squash all the commits into a single commit.
The output should look something like this:
$ git fetch http://mysite.com/my_other_project.git master
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (133/133), done.
remote: Total 338 (delta 101), reused 338 (delta 101)
Receiving objects: 100% (338/338), 71.46 KiB | 0 bytes/s, done.
Resolving deltas: 100% (101/101), done.
From http://mysite.com/my_other_project.git
* branch master -> FETCH_HEAD
Added dir 'my-subdirectory'
If we display the log of the project, we’ll see the addition of this repository and its squashed commits as a merge commit:
commit 9702b4c1bfe0f8ffdb423ef6d511a18e040a98b0
Author: Ryan Irelan <[email protected]>
Date: Fri Apr 15 15:36:45 2016 -0500
Squashed 'my_other_project' content
from commit 02199ea
git-subtree-dir: my_subdirectory
git-subtree-split: 02199ea0080d744ec76b79d74ce56d51d25cf7ae
To update the subtree repository we need to run subtree pull
:
$ git subtree pull --prefix my-subdirectory
http://mysite.com/my_other_project.git master --squash
Yes, that’s another long command just to pull down changes. This is a major draw back of using subtrees over submodules.(fn) But no solution will be perfect; choose the one that makes the most sense with your workflow.