On named branches in Mercurial
Posted at 08:00 on 22 February 2011
There seems to be a common misconception among some Git users that in order to branch your code in Mercurial, you have to clone your repository. While some Mercurial users prefer to work that way, it isn’t actually necessary, and Mercurial does provide you with a much more lightweight alternative. The easiest way to branch your code is simply to hg update
to the revision off which you wish to branch, then when you next hg commit
, it will implicitly create a new branch for you. Similarly, when you hg merge
, it will implicitly close the branch off. I tend to use a mixture of the two approaches, with repository clones for longer-running feature branches, and in-place branching for ad-hoc experimentation, smaller features, and the like.
A lot of confusion seems to centre round the concept of named branches though. If you’re used to the way Git works, you’d be forgiven for thinking that pulling from a remote repository would replace your “foo” branch with the incoming one, sending your work off to be garbage collected unless you merge immediately after pulling. Mercurial doesn’t actually work that way -- what you get is two parallel branches, both called “foo”, which you can then merge, rebase or strip out as appropriate. This is because Mercurial tends to view the DAG as more immutable than Git does, and if you want to remove branches that are no longer needed, you do it explicitly using hg strip
(a part of the Mercurial Queues extension).
For what it’s worth, I don’t like the way Mercurial uses the word “branch” here, since it doesn’t accurately reflect what you expect the word “branch” to mean: a single code line where every node in the DAG has exactly one parent and exactly one child. It seems to me that it’s something of a leftover from centralised, line-based tools such as Subversion and Perforce, where every branch has to have a name because of the need to place it somewhere in the file system.
But I don’t find it a big deal. I find the best way to handle branching and merging in Mercurial is to view your branches as essentially anonymous. Branch names, tags and bookmarks then become purely a documentation layer added on top of the DAG. I personally view branch names in particular as largely vestigial and almost never use them -- I always commit exclusively to default, and generally recommend others to do the same unless they have a valid use case for them. If you need to keep track of which head is which, the bookmarks extension provides similar functionality to Git branches, and is far less confusing.
Incidentally, one DVCS that does seem to require you to clone your repository in order to create a new branch is Bazaar. I’ve spent a few hours tinkering with Bazaar on and off over the past few months and I haven’t yet been able to find a way to branch in-place similar to hg update
/edit/hg commit
or git branch
. Perhaps someone could enlighten me?