Thursday, October 1, 2009

Rebasing in Mercurial

After I used git for my own projects for a while, we switched the development of the STRING and STITCH databases from svn to mercurial (on bitbucket). Coming from git, I found two essential things lacking: (1) automatic coloring and paging of diffs and (2) rebasing.

Problem 1 is solved by enabling the pager and using the "attend" option to specify which command should go to less. You'll also have to globally set the options "SR" for less (e.g. "setenv LESS SR").

To rebase means to take code changes that were developed in parallel and make it look like they were developed sequentially, effectively avoiding commits which have the only purpose of merging independent changes. Rebasing before pushing also avoids the problem that you can silently drop previous changes by pushing without pulling beforehand:
That is, the branch name is stored in the changeset. The flaw is that it's quite easy to have more than one branch with the same name, and it's difficult to tell when this has happened. This can cause confusion in a team where one is left wondering what changes, exactly, have made it into the "stable" branch when multiple people have reopened and merged the branch on different timelines.
The problem of the "pointless" merges is solved beautifully by the rebase extension, which is included by default in current versions of hg. I think this extension is under-advertised.

To briefly compare mercurial and git: I think git's approach is a more radical break from subversion etc. and therefore more consistent. However, it's also harder to wrap your head around, which is why we chose mercurial in the end.

For reference, here's my .hgrc.

No comments: