Ionrock Dot Org

by Eric Larson

My Weblog

Some Thoughts on Mercurial

In changing jobs a while back I also had the opportunity to change version control systems from Subversion to Mercurial. I had been a fan of Mercurial, but my usage was rather limited. When I actually had to get serious about using hg, things were not as smooth as I would have hoped.

The biggest issue was my own misunderstandings regarding what you could do with hg. I was under the impression you could clone a repo, make changes and push selective changes back to the main repo. The key word there is selective. You can branch/clone and merge back to the main repo, but it really needs to be an all or nothing operation. Otherwise you need to go back and use something like the transplant extension to migrate specific changesets to the other repo. Transplants are also somewhat scary because there is not a separate commit operation. When you transplant, the changesets are immediately committed to the branch/repo.

The other option for working with specific changesets is to use Mercurial Queues. This method seems to be very popular among hg fans, but honestly, it was more confusing than working with branches and transplant. I gave it a try on a small test repo and things broke almost immediately. While I can't recall exactly what the error messages were, I do remember it was a pain to fix. The biggest problem with MQ was that it used an entirely different model. The idea of working with patchsets seems appealing, but I got the impression that one really needed to commit to using Queues for things to really work as advertised. Just to be clear though, the chances for user error were pretty high. If a hg guru were to show me the right way to work on these things, I have no doubts much of my confusion could be cleared up.

The other huge frustration with Mercurial was the concept of heads. I sort of understand heads as divergent directions within one branch. So, if a branch has two heads, then there are almost two sub-branches (the heads) within the single branch. At the 5000 ft level, this seems pretty clear. As you work in a branch, you are also working in a head. If you pull changes from someone else, that creates a new head. To remove the extra heads (you really don't need two working heads) you need to merge the two heads back into one. This effectively is the same thing as merging two branches, with the outcome being a single head or branch. Again, from a design perspective, this makes perfect sense. Where things get sticky is when a problem arises due to conflicts. For example, I ended up making changes in a branch that I should have worked on in the default branch (I'll go into the tip/default issues next) and merged back into the versioned branch. For whatever reason, every time I needed to commit to the versioned branch, conflicts would need to be resolved for one file. This ended up getting propagated to others as well after pushing to the main repo. Again, user error could have easily been the cause, but fixing the problem was next to impossible.

Lastly, the distinction between tip and default is just weird. You'll notice above I mention working in a branch. This is because you need to realize you are always in branch, even if it is the "default" branch. If you ever consider yourself working in the "head" or "trunk", you'll run into problems. My understanding is that the default branch is the branch you change into when you do something like "hg up" without any arguments. I've eventually become explicit about this by always doing "hg up default" if I want to work on the "trunk". So far, thinking in terms of always using a branch is very helpful. Where things get odd is the idea of "tip". To this day I still don't truly understand what "tip" really is. If you do a "hg tip" it will tell you the most recently added changeset, in the most recently changed head (hg help tip). Again, the big picture makes sense. The problem is that you can use other commands on the "tip" such as the "heads" command. If the tip is the most recent changeset in the most recent head, then it would seem that doing something like "hg heads tip" must refer to something larger, such as the current or default branch. The truth is I have no idea what it refers to, so my resolution has been to always pay attention to the branch I'm in and never use "tip" for anything.

Overall, the idea of a DVCS is really great. When Mercurial has been working for me, it is actually really nice and doesn't require much extra work. When I think of alternatives (Subversion + DVCS), it always seems like a messy solution that is solvable by a single DVCS. The biggest benefit I've gotten from Mercurial is the need to pay close attention to what I'm doing with my VCS. I've become very conscious of what operations I'm doing and how they impact the tree as a whole. Mercurial requires cognitive thought in order to keep track of all the details, but in the end, it has been good practice for me.

Posted Tue Nov 11 20:16:39 2008 by Eric Larson
Created using Python, jQuery and Emacs