19 June, 2008
We’re using Mercurial here at LShift for much of our development work, now, and we’re finding it a great tool. We make heavy use of branches (”branch per bug”) for many projects, and this is also a pretty smooth experience. One issue that has come up is policy regarding merging the trunk (”default”) into any long-lived feature/bug branches: should you do it, or should you not?
My vote is that you should merge default into long-lived branches fairly regularly; otherwise, you have a big-bang, all-at-once nightmare of a merge looming ahead of you. If you do merge frequently, though, there’s one subtlety to be aware of:
hg diff is not history aware, so in order to get an accurate, focussed picture of all the changes that have been made on your long-lived branch, you need to do one of two things:
- either, merge default into your long-lived branch right before you merge the long-lived branch back into default, and run
hg diffafter that’s complete; or
- (recommended) do a throw-away test-merge of the long-lived branch into default directly.
Imagine a history like this:
(2) (3) | | \ / V | (1)
… where (1) is an ancestral revision, (2) is the default branch, and (3) is the long-lived branch - let’s call it “foo”.
Given this history, running
hg update -C default (to make the working copy be the default branch, i.e. revision (2)) followed by
hg diff foo will give you a misleading diff - one that undoes the changes (1) to (2) before doing the changes from (1) to (3). This is almost certainly not what you want!
Instead, run a test merge, by
hg update -C default followed by
hg merge foo and then plain old
hg diff. Note that this modifies your working copy! You will need to revert (by
hg update -C default) if you decide the merge isn’t ready to be committed.
The output of
hg diff after the
hg merge shows a history-aware summary of the changes that the merge would introduce to your checked-out branch. It’s this history-awareness (”three-way merge”) that makes it so much superior to the history-unaware simple diff (”two-way merge”).