Git versus mercurial…

I’ve been playing now with git and mercurial lately. Between rails developers choosing git and all of Sun switching to mercurial, I wanted to see which made more sense. What I liked about CVS was the ability to tag things. Tags were cheap, but branching ‘felt’ expensive. Subversion was faster then CVS, worked better remotely, directories were in the ‘version history’, and branching was cheap. But tags really didn’t exist. Plus any changes changed the latest revision in any branch or tag, which is dumb. Interacting with the repository also required you to be online, and with a reasonable connection speed, just like CVS. (At least svn was faster then cvs there)

There is no argument against a distributed VCS, especially if they fix the problems with subversion, but which one? The most popular are git and mercurial… so darcs feels alone these days. Git and mercurial are basically feature complete with each other. Both get the job done, but they are built with different core preferences which seems to be evident from their resulting executables. Git was written by Linux kernel hackers using lots of perl scripts with a basic wrapper for most activities. Mercurial is a python script written by application-level coders. Again, 95% of the usage patterns are the same for each of these. Some differences have <a href=””>been documented</a> before, and here are mine which include information from that blog post:

The mercurial script can serve the repository itself. Both git and hg allow for using HTTP/S for accessing a code repository like mod_dav_svn for subversion, and both make use of SSH for pushing/pulling repository information. Git has a separate daemon that you have to run to make use of the ‘git’ protocol, whereas I can call ‘serve’ on the hg program to make my code available from my desktop right away. Git requires more configuration to get it working. For this, I prefer mercurial.

Mercurial considers commits immutable by default, whereas git is flexible, and allows for changes against the history in the revision.  I really like the immutable approach… and even subversion’s constant updates to tags isn’t changing history like git can. So, I really like how mercurial handles this as opposed to git. But this leads to other differences in how branches are dealt with in mercurial and git.

Branching is a very strong point of git, and shows the Linux kernel hackers influence. Branches in Mercurial are permanent, so failed branches live forever. (Immutability) Git branches can be dropped from the repository completely. The head of a branch in mercurial is ‘inferred’ by having no children, where as they are explicit in git. (Here, git is more like the CVS tagging HEAD technique and mercurial is more like subversion. Note that _both_ are better then subversion, but implicit versus explicit ‘head’ of a tree is a big difference) Git branching is a stronger system then mercurial for your developers, though mercurial may be better if you want to force history does not change. This is most likely why Linus made/picked git and why Sun picked Mercurial.

Overall, I can easily argue for either solution. Active development in a rails application does not require git, and writing a Java application does not require mercurial. You can use CVS with either if you wanted. Do not let the communities force you in a direction. On my desktop, I have RCS commands, svn, git, hg and darcs. They don’t collide with each other, both are fast for committing code changes and pulling/pushing repository changes, so choose the one for your project you like and makes more sense for your business.


One thought on “Git versus mercurial…

  1. Jakub Narebski says:

    Actually commits in Git are also immutable. What you can do instead (note the “can” here, as you are not required to use this feature) is to rewrite history, and then prune old version of history. The rule of thumb is that you should not change published history.

    I find correcting last commit to be very useful (as far as I know you can do this by undoing and redoing last commit in Mercurial). I think that git-rebase was created to better deal with patch+email based workflows, to be able to create patch series which would apply cleanly on top of current version (equivalent functionality can be found in Mercurial by using Transplant extension, and in Bazaar-NG by using Grafts extension/plugin). git-filter-branch (and formerly cg-admin-rewrite-hist in Cogito) has its uses for example to purge accidentally comitted file from the whole history.

    By the way, you are talking at beginning about tags, how it was one of stronger points of CVS, and how Subversion (because of misguided “copy is cheap” branching as directory approach) didn’t quite get it right… but then when talking about distributed version control systems, comparing Marcurial and Git (BTW. what about Bazaar-NG?) you forgot about this issue. I think that Git got tagging right, with tags which are unversioned and propagatable (transferable), and Mercurial didn’t: it looks like tagging was added as afterthought (and therefore for example must use a lot of special casing, special treatment for .hgtags). Git additionally allow for annotated tags, and annotated tags can be also PGP-signed. git-describe command for example makes heavy use of tags, with output like v1.6.0.2-534-g053e24a describing how many commits we are since last tag. By default tags are auto-followed, meaning that if you get commits you also get all tags which points to those commits.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s