Subtree is a way to embed other git repository histories into your own by merging in the subtree history into yours. It also enables you to push patches to the subtree repository. This allows you to grab source change directly via merging histories, as well as pushing them back.
This feature is useful if you decide that for instance a specific folder should be a repository on its own because other repositories/projects would need it.
- Run
./setup.sh
NOTE: If running setup.sh on windows, you can run into problems by sourcing the setup script. Instead, run
./setup.sh, and the folders would be created correctly.
After running . setup.sh or . ./setup.sh, you'll have two repositories that we will use for this exercise.
INFO: You now have the following under the excercise directory:
- A
productrepository that contains the "product" history. - A
componentrepository that contains the "component" history.
Exercise
- Go to the
componentrepository and rungit logand notice the history. - Go to the
productrepository and rungit logand notice the history. - Add the
componentrepo as a remote reference:git remote add component ../component/.git( optional, but good practice ) - Check the remotes using
git remote -vand it should look like this:
$ git remote -v
component ../component/.git (fetch)
component ../component/.git (push)
- Add the
componenthistory to the this repository (product) under the directorycomponent:git subtree add --prefix component component master. You should see something like this:
git fetch component master
warning: no common commits
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 224 bytes | 18.00 KiB/s, done.
From ../component/
* branch master -> FETCH_HEAD
* [new branch] master -> component/master
Added dir 'component'
- Please explain what happend and what the result is. Consider running this command in both
productandcomponentrepositories.git log --graph --decorate --oneline --alland explain the common history and the newest commit inproduct.
We have added the component subtree to the component directory also named a prefixin subtree terms. We now want add changes to the component and integrate them into the product
- Go to the
componentrepository - Make changes and commit them
- Go to the
productrepository and pull in the changes with this command:git subtree pull --prefix component component master
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 276 bytes | 5.00 KiB/s, done.
From ../component/
* branch master -> FETCH_HEAD
99d28dd..a930ba9 master -> component/master
Merge made by the 'recursive' strategy.
component/component.h | 1 +
1 file changed, 1 insertion(+)
- Please explain what happend and what the result is. Consider running this command in both
productandcomponentrepositories.git log --graph --decorate --oneline --alland explain the common history and the newest commits inproduct.
We have updated component directory from the component repository. We now want to modify the component directory and deliver the changes to the component repository. NOTE: We push to a new branch.
- Go to the
productrepository. - Go to the
componentdirectory and make changes and commit them. - We want to deliver the changes just made to the
componentrepository using this command:git subtree push --prefix component component patch.
git push using: component patch
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 357 bytes | 357.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To ../component/.git
* [new branch] e6fb29fe9a6213a9806e86195c609ba0bfd94249 -> patch
- Please explain what happend and what the result is. Consider running this command in both
productandcomponentrepositories.git log --graph --decorate --oneline --alland explain the common history and the newest commits inproduct. - Why do we push to a new branch?
- How would you do it if you not owner nor collaborator on the
componentrepository on for example GitHub?
git log --graph --decorate --oneline --allgit subtree add --prefix component component mastergit remote add component ../component/.gitgit subtree push --prefix <prefix/directory> <repo> <branch>
Run all the above commands to see the commands and their results.
replay=true debug=true ./setup.sh
We found some resources that may assist you in understanding this feature of Git better.