Tuesday, January 28, 2014

git subtree merge strategy in your everyday life

Here is yet another post on the super useful git feature called the subtree merge strategy. Not to be confused with the newish git-subtree command, which uses this strategy, but may or may not be completely ready for general consumption. Imagine a use case where you have a package, for example hg-fast-export, that you want to use in your project. You want to deploy it with your project, so you consider using git submodule. An alternative would be to use the git subtree merge strategy. There are numerous sites that explain the pros and cons of subtree merge vs submodules.
~/myproj (master)$ git remote add hg-fast-export https://github.com/frej/fast-export.git
~/myproj (master)$ git fetch hg-fast-export master
~/myproj (master)$ git read-tree --prefix=hg-fast-export/ -u remotes/hg-fast-export/master
~/myproj (master)$ git pull --squash -s subtree --no-commit hg-fast-export master
~/myproj (master)$ git pull --squash -s recursive -Xsubtree=hg-fast-export/ --no-commit hg-fast-export master
~/myproj (master)$ git diff-tree hg-fast-export master
  1. Add the remote that hosts the sub-package.
  2. Fetch the branch from the remote that you want to use in your project.
  3. Read the remote branch into its own folder tree in the working copy. The name of the new directory is provided by the prefix if you append a slash at the end.
  4. Merge updates from the sub-package into the hg-fast-export tree, squash them all into a single commit, but don't auto-commit. This gives you a chance to check the merge, before commiting. Merge prepopulates the message with a summary of the commit messages from the sub-package's remote branch.
  5. Explicitly specify trees to merge if Git subtree merge strategy can't determine by itself.
  6. Get diff between two trees.
I think if you want to push from your sub-package back to the remote, you would want to create an orphan branch, and push from there. This is covered in the alternate posts linked to from here.

Pushing to gh-pages for Github pages is a perfect use of subtree merge strategy - I provide an example in this SO answer.
Fork me on GitHub