Over the weekend I started using topgit (README), a git wrapper that takes most of the work out of managing dependent “topic branches.” The gist is that you mark branches as depending on one another. Then, when you modify a branch, you can use the
tg updatecommand to propagate those changes to any branches that depend on it.
I’ve been doing a lot of large changes and refactorings recently, so what topgit really means for me is never having to wait for code reviews to keep working.
The basic workflow goes like this:
“refactor” is the name of my new branch, “blogger” is the trunk
$ tg create refactor blogger
hack hack hack
mv mv mv
add add add
commit commit commit
now mail out the CL for review
$ gitwrapper mail -m reviewer
In a pure Perforce environment, I couldn’t continue working on this code at all until the review came back and I could submit. With vanilla git, I can of course
git checkout -b new-branchand keep going, and this is fine most of the time.
Where it starts to get sticky is when my reviewer has comments. No big deal, though. I can just
git checkoutback to the
refactorbranch, make those changes, and commit them.
Of course, I now need to update my
new-branchso that I’m working from the latest intermediate state.
git merge refactorhandles that fairly well (sometimes I get pedantic and use
git rebase) and I’m back to coding the new feature.
topgit supports exactly this pattern of development by automating the “update the
new-branch” step. If I created the
tg create, then I could run
tg updateto merge in the latest versions of all of
To continue, we have:
git checkout refactor
tweak tweak tweak
git commit -am "fixes from review"
git checkout new-branch
code code code
“All” is a very operative word in that last sentence. With topgit, a branch can have several dependencies, forming a DAG, and it will recursively update each one of them. This means that I can have several independent changes, with each out for review in parallel, but continue development on a new change that relies on all of them.
topgit works by keeping a separate reference branch for each topgit-managed branch. When you run
tg update, it merges the dependencies into this branch, then merges that into the normal branch. This gives the added benefit that you can easily
git rebaseagainst the reference branch to clean up your commit graph.