Git vs. Mercurial: Please Relax

August 7, 2008 at 7:12 pm 27 comments

Everyone’s up in arms to embrace distributed version control as the new must-have tool for the developer in the know. Though many people have not yet migrated from Subversion, those that have almost invariably extoll the virtues of their particular choice. But though all of the major DVCS’s have features that set them above the previous generation of centralized systems, none stands head-and-shoulders above the others as Subversion does among the last generation: each of them was designed for a specific purpose, and each of them will serve those with different habits, workflows and development styles differently. Having used both git and Mercurial for the better part of a year, I’ve had the opportunity to compare the two. It saddened me to see a Twitter-based debate flamewar erupt over which is better, so I thought I’d do my best to try and ease the tension – with analogies!

Git is MacGyver

 

great man or greatest man?

 

 

Git’s design philosophy is unmistakably that of Unix: unlike Subversion, CVS, or Mercurial, git is not one monolithic binary but a multitude of individual tools, ranging from high-level “porcelain” commands such as git-pull, git-merge, and git-checkout to low-level “plumbing” commands such as git-apply, git-hash-object and git-merge-file. So, like MacGyver, you can do just about anything you need with Git – this includes totally awesome Wiki engines, issue trackers, filesystems, sysadmin tools – everything short of fuse repair:

As such, git is not so much a version control system as it is a tool for building your own version-controlled workflow. For example, when faced with the fact that no git tool performs the equivalent of hg addremove – a useful Mercurial command that adds all untracked files and removes all missing files – I found one line to a script originally written by James Robey:


#!/usr/bin/env bash
# git-addremove
git add .
git ls-files -deleted | xargs git rm

Git’s branching, tagging, merging, and rebasing are near flawless: git’s merging algorithm is close to omniscient, having once merged 12 Linux kernel patches simultaneously. Additionally, git provides you with tools to go back in time and edit your commit history – useful for those of us who have left certain critical elements out of a commit and had to quickly recommit with a helpful message such as “oops”. (And when I say “those of us”, I mean “every developer, ever”.) Personally, I elect to only use this feature to edit my last commit (using git commit --amend); I have never needed or wanted to meddle further with the past. git is also extremely fast thanks to its C codebase.

There is no better emblem of git’s flexibility than GitHub. GitHub’s rise to success has been positively meteoric, and with good reason. It’s a brilliantly-designed site that serves as more than a pretty, browsable frontend to my source tree in that it brings a social aspect to programming – using Git, I can fork anyone’s project, make my changes, petition for them to be included in the main repository, and pull other people’s changes to mine. Though it took a while for me to adjust to the anarchic notion of every user having their own equally-valid fork of a project – shouldn’t there be one definitive version of a project? – I realized its potential when working with other contributors to Nu. Add the fact that GitHub is one of the most solid and reliable services I’ve ever used, and you’ve got what very well might be the deal-breaker in the fight for DVCS dominance.

On the other hand, migrating from Subversion/CVS to git requires a lot of work. Linus has made it clear that he disagrees with the fundamental ideas behind Subversion/CVS, referring to SVN as “the most pointless project ever started”. As such, the git project has consciously made no effort to make the migration to git easy: the revert command in Subversion resets your current working copy to the last commit, but in git undoes a supplied patch and commits the changes needed to remove that patch. (The equivalent command for svn revert in git is git reset --hard HEAD^.) Whining about this on the git mailing list is a little like this:

Get it? No? Too bad.

Get it? No? Too bad.

Apparently the choices that Linus et. al made when designing git are sensible – if, of course, you understand the internal structure of git and how it stores your data. I’m afraid I’m only halfway through PeepCode’s great Git Internals, so I can’t comment on whether that statement is true. But I have to admit that if I had to read a $9, 100-page PDF to learn every new tool I downloaded, I would have no time and no money.

This brings us to another of git’s faults: its documentation is terrible. Man pages are no longer a sufficient replacement for a good, well-updated wiki or reference work; git’s wiki still has a long, long way to go. Add in the fact that since, like many OS X users, I installed git through MacPorts, only the main git tool comes with a man page, leaving me to consult the Web to find out exactly how to format revision specifiers. I’ve observed that developers that were able to learn git from colleagues already familiar with git and its internals tend to have a higher opinion of it, in contrast to people such as myself that had to waste a lot of time digging around through Google and the man pages.

However, considering the fact that git is supposed to be a platform, one would suppose that it would have clear, bridgable functions to reuse in your own C projects and bridge to other languages. One would be completely wrong – libgit.a is a joke, and the Ruby git gem (and my own vastly-inferior Nu/Git bindings) depend on running shell commands and parsing the output, which really gets quite tiresome after a while. The fact that console output may differ from platform to platform and any new feature may change the format of console output makes me very reluctant to commit to maintaining my Nu/Git bridge. (I swear, that’s the reason. It’s not because I’m lazy.)

In conclusion, Git is perfect for command-line wizards, people with large teams and complicated projects, and those who need their DVCS to be endlessly configurable. Certain developers have a workflow which, when interrupted, causes much grief and lamentation – if that description fits you, then git is almost certainly what you want, because it can be molded to fit the most esoteric workflow. Solo developers and those accustomed to working with centralized VCS’s may find git to be hostile, unfriendly and needlessly complex. When I work on a large project with many committers, I prefer git and GitHub.

Mercurial is James Bond


mercurial |mərˌkyoŏrēəl|
adjective
1) Subject to sudden or unpredictable changes of mood or mind: his mercurial temperament.

Though there have been many unfortunate open-source project names, Mercurial (also referred to by its command-line-tool name, hg) is both apt and unfortunate: though it is definitely speedy, both in terms of learning curve and execution speed, it is also at times inconsistent, maddening, and unpredictable. Mercurial is like James Bond: though they are not suited for each and every job, put them in a situation for which they are prepared and you will get things done. (If your programming job is as exciting as a Bond movie, please get in touch with me right away when one of your programmers is killed in action.)

In contrast to git’s philosophy of providing a flexible platform built out of individual components, Mercurial is monolithic and (relatively) inflexible. Developers who like to keep their system clean will probably appreciate the fact that hg installs one binary in contrast to the 144 that make up git, and developers who think that git’s ability to edit your previous commits is moronic, unnecessary, and dangerous will appreciate the simplicity hg provides by omitting that particular feature.

Compared to git, hg’s branching, merging and tagging systems are equally powerful and only slightly slower. The only current flaw in Mercurial’s branching system – and sweet crouching Jesus, is it ever a huge flaw – is that deleting named branches is unbelievably difficult: as far as I can tell, the only way to do so is to learn and enable the patch-queuing system (about which I have heard raves, but have not had the time yet to sit down and grok) and use the hg strip command, or install the local-branches extension. Selenium currently recommend you use tags instead of branches, which practically redefines the concept of a half-assed solution.

Despite that glaring flaw, the rest of hg is excellent. It functions almost identically to Subversion in the commands that it shares, and the new concepts – branching, merging, etc. – are easily learned and intuitive. Whereas I’m still learning how to do relatively basic things in git, I learned pretty much all of hg’s functionality in about a day. If you’re familiar with Subversion, transitioning to Mercurial should be a piece of cake – the functions you’re familiar with will be there, and the new functions are easy-to-learn and well-documented.

Though I’ve never tried to integrate Mercurial’s functionality into my own projects, I hear that since it’s written in Python it’s very easy just to import its classes and call them programatically rather than parse the output of shell scripts. I wanted to write a Mercurial frontend for OS X (I was planning to call it ‘hermetic’ – get the elaborate literary pun?), but the viral nature of the GPL discouraged me – since no company has granted me stock options for my code, I’m a little reluctant to just give away the fruits of my labors. Mercurial’s answer to GitHub is BitBucket, which I have not tried yet. If I do, I will update this entry posthaste.

In conclusion, Mercurial is the yin to git’s yang: those such as myself who are constantly experimenting with new ways to work and write code will object less to the restrictions that hg imposes on workflows. After switching to Mercurial for a small two-person project last year, my collaborator observed that Mercurial feels a lot more Mac-like – usability and smoothness of operation trump Unix philosophy when necessary. If I don’t have to share my code with anyone, I tend to use Mercurial in order to get things done faster.

So, What’s My Point?

To paraphrase Colin Wheeler, it’s OK to proselytize to those who have not switched to a distrubuted VCS yet, but trying to convert a git user to Mercurial (or vice-versa) is a waste of everyone’s time and energy. If you want to switch to a DVCS, then here are five easy steps:

  1. Evaluate your workflow and decide which tool suits you best.
  2. Learn how to use your chosen tool as well as you possibly can.
  3. Help newbies to make the transition.
  4. Shut up about the tools you use and write some code.

Entry filed under: code, problems, programming, rant. Tags: , , , , , , .

“Haskell Curry? Yes, I dated his daughter.” A Deeply Skeptical Look at C++0x

27 Comments

  • 1. Al  |  August 8, 2008 at 12:01 am

    Great post, is a nice introductory description of both systems.

    I’m more of the Merurial camp, I’m a rabid linux user but the feeling of something that just_works is great (maybe is because I’m getting old and my brain is beginning to dry…)

    About the MQ (Mercurial Queues) thing you are right, this gives the extra-punch that you need sometimes. If you think about, this “separation of complexity” is great. Right now you’re using a simple system and don’t worrying about that shiny queues thing, but it you need it is just there for you to learn… and it’s not that hard, trust me.

    To make it short MQ works as a stack of patches over your repository. You can convert normal commits to patches and viceversa; and in patch-land you can do all those nifty things like changing history, deleting patches, folding several of then into one… then as you can guess just convert it into commits and presto! history rewritten.

    This of course is discouraged in public repositories, but is there if you want to use it.

    And also a patch queue allows you to have your local changes and rebase them against a moving repository (they are always “above” the normal commits). Even you can setup a patch queue over some decompressed tgz and maintain local modifications over some external software package and its upgrade history.

  • 2. Jonno  |  August 8, 2008 at 5:32 am

    Good thing the Mercurial and Git guys were not worried about giving away the fruits of their labour otherwise instead of paying $9 for a PDF you would be paying $200/developer!

  • 3. Nicolás Sanguinetti  |  August 8, 2008 at 6:27 am

    You can enable the doc variant in macports when installing git-core (sudo port install git-core +doc) to install all the man pages.

    In any case, I agree that documentation for git is, at best, incomplete. I’ve been using it for about a year — but, for serious, day to day management of my source code for about 2 months (at my company, and about 6 months for personal projects) and I got to the point I don’t need to ask for help every time I run into something maybe 2 or 3 months ago. But I still consult the manpages regularly…

    I haven’t used Mercurial though, so I can’t say anything in favor -or against- hg.

    Good post, nonetheless 🙂

  • 4. Martin DeMello  |  August 8, 2008 at 10:36 am

    https://twitter.com/_why/statuses/873705618

    Speaking of unfortunate names 🙂

  • 5. Scott Chacon  |  August 8, 2008 at 3:57 pm

    I am trying to work on a nicer resource for learning Git that is an open-source book. If you (or anyone else) is interested in helping out, I’ve started it here : http://book.git-scm.com/

    Right now much of it is pulled together from the User Guide and tutorials, but a lot of it is new and I’m hoping it will eventually be a good, simple resource for learning Git.

  • 6. Mike Taht  |  August 8, 2008 at 4:49 pm

    Good article and analogies.

    I note that one of *my* favorite features of git is the online manual pages and the web tutorials. While the documentation is not perfect – it is readily available offline, and integrated into the the tools themselves – in my case I am frequently disconnected from the internet entirely and having most of the doc NOT in a wiki or some other form of online tool is a genuine boon.

  • 7. Caleb Cushing (xenoterracide)  |  August 8, 2008 at 5:44 pm

    being a git linux user every git tool has a man page.

    it’s just man git- e.g. git-commit, git-checkout

    also gittutorial if your distributor doesn’t package these I would complain.

  • 8. Tim Harris  |  August 8, 2008 at 6:10 pm

    “If your programming job is as exciting as a Bond movie, please get in touch with me right away when one of our programmers is killed in action.” I think you missed out a “y”: “If your programming job is as exciting as a Bond movie, please get in touch with me right away when one of your programmers is killed in action.”

    Interesting article, Thanks!

  • 9. Kevin Ballard  |  August 8, 2008 at 8:01 pm

    You mentioned that “libgit.a is a joke”. I wanted to point out that libgit.a is *not*, I repeat *not* meant to be used by third-party programs. It’s strictly an internal-use-only library, and its API is by no means guaranteed to be stable.

    Also, I believe the Grit ruby gem is learning how to manipulate the git object graph without shelling out to git tools.

  • 10. buyblogger  |  August 8, 2008 at 9:59 pm

    you are good job man

  • 11. Reg Braithwaite  |  August 9, 2008 at 3:27 am

    I’d like to point out that like Mercurial, Ick’s name is apt considering the implications of messing with Ruby’s evaluation model on the fly…

  • 12. Manlio Perillo  |  August 9, 2008 at 5:41 pm

    Great article, but I disagree with “Mercurial is monolithic and (relatively) inflexible”.

    Mercurial is written in Python, and Python, unlike C, has modules.

    So Mercurial is quite modular, but instead of having N heterogeneous scripts, it has N subcommands, and user can add new subcommands using a convenient API.

    Ah, and there is a (still very draft) project for the implementation of a wiki based on Mercurial (using its low level API)l:
    http://hg.mperillo.ath.cx/wsgix/file/tip/wsgix/contrib/flatpages/
    http://hg.mperillo.ath.cx/wsgix/examples/file/tip/wiki/

  • 13. Top Posts « WordPress.com  |  August 10, 2008 at 12:06 am

    […] Git vs. Mercurial: Please Relax Everyone’s up in arms to embrace distributed version control as the new must-have tool for the developer in the […] […]

  • […] Please Relax « Important Shock Published in August 9th, 2008 Posted by cmoewes in Applications Git vs. Mercurial: Please Relax « Important ShockThis great write up does a fantastic job of describing git and mercurial. If you are looking to […]

  • 15. links for 2008-08-09 [delicious.com] | Libin Pan  |  August 10, 2008 at 6:31 am

    […] Git vs. Mercurial: Please Relax « Important Shock Git vs. Mercurial: Please Relax (tags: versioncontrol git mercurial) […]

  • 16. Grant  |  August 11, 2008 at 12:20 am

    Okay, nice article; however, I have to take exception to your statements regarding the ‘viral nature of the GPL.’

    Mercurial is licensed under the GPL, but that says nothing about the code you would write to create a OS X GUI for it. There’s no reason you couldn’t keep your front-end code closed source and distribute it as you wish.

  • 17. Arne Babenhauserheide  |  September 7, 2008 at 7:39 pm

    Thanks for your article!

    I like the analogies 🙂

    -> I added it to my Mercurial vs. Git linklist 🙂

    There’s one thing I’d like to comment on, though:

    Adapting Mercurial is very easy. You can write an extension which can access every low level function and overwrite every command if it needs to.

    You don’t need to do any commandline parsing or such – instead just use the “ui” object every commands gets as first parameter to communicate with the user while using the “repo” parameter to perform various lower-level tasks.

    Also you can just import and use any other command Mercurial offers to get your job done.

  • 18. dhruva  |  October 5, 2008 at 7:00 am

    If you want to develop on multiple platforms and be able to seamlessly share code (without using NFS/CIFS or shared file system), stick to mercurial/hg. Git daemon does not work on windows and I find this a rather basic necessity.
    From a hacker perspective, I still find hg simpler. Once the git book is out, I might get a better understanding of git to be able to hack git.

  • 19. Javier  |  October 20, 2008 at 2:36 pm

    I would say that Git is not like McGyver, but like the A-Team. A bunch of people specialized on certain tasks (a bunch of binaries that do different tasks).

  • 20. sz  |  October 26, 2008 at 4:11 pm

    Maybe it’s too late now, but anyway:

    The equivalent command for svn revert in git is git reset –hard HEAD^.

    It is ‘git reset –hard HEAD’, without the ^ at the end, which is a fundamental difference.

    However, if you want to do ‘svn revert some/file’, then it’s ‘git checkout some/file’. Oh well.

  • 21. sz  |  October 26, 2008 at 4:27 pm

    Two notes to my previous comment:

    1. ‘git reset –hard’ is enough, because it defaults to HEAD if no commit is given.

    2. Alternatively, you can do a whole-tree revert with ‘git checkout .’ (while in the root directory of the repository), so the UI is not that inconsistent anymore. But it might be frustrating to svn users, because ‘git checkout’ and ‘svn checkout’ do different things.

  • 22. Ben Spaulding  |  November 11, 2008 at 7:23 pm

    I think git add -A is what you are looking for when you find yourself missing hg addremove. See the git-add docs.

  • 23. Chris Knadle  |  November 14, 2008 at 2:52 pm

    I found it hard to believe that Git would store separate copies of several binaries, so I used the ‘stat’ command to look at them — and I found that several of the binaries (at least on Debian) are HARD LINKS. This is unusual, so here’s an illustration:

    $ ls -l git git-add
    -rwxr-xr-x 88 root root 823536 2008-08-25 06:40 git
    -rwxr-xr-x 88 root root 823536 2008-08-25 06:40 git-add

    $ stat git git-add
    File: `git’
    Size: 823536 Blocks: 1616 IO Block: 4096 regular file
    Device: 2103h/8451d Inode: 25477044 Links: 88

    File: `git-add’
    Size: 823536 Blocks: 1616 IO Block: 4096 regular file
    Device: 2103h/8451d Inode: 25477044 Links: 88

    Both binaries use the same inode, so they’re hard links! Also note the link count — this means at least 88 of the 149 git binaries are actually only hard links to a single binary on the disk — even though it APPEARS as though there are multiple copies. Usually this is done with soft links instead, which stand out as being links rather than files, but for some reason hard links were chosen in this case instead… very interesting.

  • […] Git vs. Mercurial: Please Relax […]

  • 25. Ant » Blog Archive » Git - My new SCM tool  |  December 25, 2008 at 12:26 pm

    […] git 與 mercurial 比較。其實我覺得就像這篇文章所說的,git 就像是馬蓋先 (MacGyver),而 mercurial 就像是 007 (James […]

  • 26. gcoder  |  January 2, 2009 at 12:27 am

    I know I’m a bit late to the “party”, but I was just on a mercurial/git research trek (the second one, first was almost a year ago or so). My conclusion back then was, I wold have wanted to go with git, but windows support is a must so mercurial seemed like the only choice. Work kept me busy so I didn’t get around to actually do anything more.

    The past two days I basically came to the same conclusion again, allthough I was briefly fooled that git windows support was looking brighter this time around, only to realize it looks insanely dark.

    Windows explorer integration projects ToroiseGit and CheetahGit are DEAD. I think this can’t be stressed enough for anyone that needs to work with windows, and thinks that these are on the horizon to salvage the situation.

    The elitist attitude from some of the Git people, is alienating and highly counter productive. I think this should also be considered as a con when comparing the different solutions. Because if you need windows, and one solution is full of anti-windows folks, it doesn’t bode well.

    What really irked me was reading the thread/comments here:
    http://kerneltrap.org/mailarchive/git/2008/10/31/3874054
    http://code.google.com/p/msysgit/wiki/GitCheetah

    hilights such as:

    “the big problem is: I do not want many people on Windows to convert to Git, since my experience is that they — expect other people to work for them. IOW I would not get anything except for some thankyous for my work”

    “and from what I’ve seen of tortoise* users, ‘stupid proof’ is very, very, very, necessary”

    This elitist and anti-UI attitude that seems to be surrounded by git really ticks me off. He can cry about windows users not contributing until his face turns blue, but the strangely enough the other Tortoises (including TortoiseHg) actually are getting done, people are working on them. Maybe, just maybe, there is an attitude problem going on that keeps people away from that particular project.

    Mind you, I’m a linux/*nix fan and user and have been for 15+ years. Yes yes MS sucks and all that, but I still need to work on windows for most things. The more platforms a solution can support, the merrier. Mercurial doesn’t seem ooze of anti-windows as git does, which is a shame, as I really really wanted to go with git. But basic UI support is a must, it’s 2009 for christsakes (it has nothing to do with intelligence), I still use the command line, and like it, for some things, everything has its place and time.

  • 27. poko  |  January 2, 2009 at 3:44 pm

    mercurial now has

    named branches
    http://hgbook.red-bean.com/hgbookch8.html#x12-1570008

    git-like (local only) branches
    http://www.selenic.com/mercurial/wiki/index.cgi/BookmarksExtension

    rebase support
    http://www.selenic.com/mercurial/wiki/index.cgi/RebaseProject


About Me



I'm Patrick Thomson. This was a blog about computer programming and computer science that I wrote in high school and college. I have since disavowed many of the views expressed on this site, but I'm keeping it around out of fondness.

If you like this, you might want to check out my Twitter or Tumblr, both of which are occasionally about code.

Blog Stats

  • 733,747 hits