727
votes

I've been using git for some time now on Windows (with msysGit) and I like the idea of distributed source control. Just recently I've been looking at Mercurial (hg) and it looks interesting. However, I can't wrap my head around the differences between hg and git.

Has anyone made a side-by-side comparison between git and hg? I'm interested to know what differs hg and git without having to jump into a fanboy discussion.

25

25 Answers

345
votes

These articles may help:

Edit: Comparing Git and Mercurial to celebrities seems to be a trend. Here's one more:

238
votes

I work on Mercurial, but fundamentally I believe both systems are equivalent. They both work with the same abstractions: a series of snapshots (changesets) which make up the history. Each changeset knows where it came from (the parent changeset) and can have many child changesets. The recent hg-git extension provides a two-way bridge between Mercurial and Git and sort of shows this point.

Git has a strong focus on mutating this history graph (with all the consequences that entails) whereas Mercurial does not encourage history rewriting, but it's easy to do anyway and the consequences of doing so are exactly what you should expect them to be (that is, if I modify a changeset you already have, your client will see it as new if you pull from me). So Mercurial has a bias towards non-destructive commands.

As for light-weight branches, then Mercurial has supported repositories with multiple branches since..., always I think. Git repositories with multiple branches are exactly that: multiple diverged strands of development in a single repository. Git then adds names to these strands and allow you to query these names remotely. The Bookmarks extension for Mercurial adds local names, and with Mercurial 1.6, you can move these bookmarks around when you push/pull..

I use Linux, but apparently TortoiseHg is faster and better than the Git equivalent on Windows (due to better usage of the poor Windows filesystem). Both http://github.com and http://bitbucket.org provide online hosting, the service at Bitbucket is great and responsive (I haven't tried github).

I chose Mercurial since it feels clean and elegant -- I was put off by the shell/Perl/Ruby scripts I got with Git. Try taking a peek at the git-instaweb.sh file if you want to know what I mean: it is a shell script which generates a Ruby script, which I think runs a webserver. The shell script generates another shell script to launch the first Ruby script. There is also a bit of Perl, for good measure.

I like the blog post that compares Mercurial and Git with James Bond and MacGyver -- Mercurial is somehow more low-key than Git. It seems to me, that people using Mercurial are not so easily impressed. This is reflected in how each system do what Linus described as "the coolest merge EVER!". In Git you can merge with an unrelated repository by doing:

git fetch <project-to-union-merge>
GIT_INDEX_FILE=.git/tmp-index git-read-tree FETCH_HEAD
GIT_INDEX_FILE=.git/tmp-index git-checkout-cache -a -u
git-update-cache --add -- (GIT_INDEX_FILE=.git/tmp-index git-ls-files)
cp .git/FETCH_HEAD .git/MERGE_HEAD
git commit

Those commands look quite arcane to my eye. In Mercurial we do:

hg pull --force <project-to-union-merge>
hg merge
hg commit

Notice how the Mercurial commands are plain and not special at all -- the only unusual thing is the --force flag to hg pull, which is needed since Mercurial will abort otherwise when you pull from an unrelated repository. It is differences like this that makes Mercurial seem more elegant to me.

73
votes

Git is a platform, Mercurial is “just” an application. Git is a versioned filesystem platform that happens to ship with a DVCS app in the box, but as normal for platform apps, it is more complex and has rougher edges than focused apps do. But this also means git’s VCS is immensely flexible, and there is a huge depth of non-source-control things you can do with git.

That is the essence of the difference.

Git is best understood from the ground up – from the repository format up. Scott Chacon’s Git Talk is an excellent primer for this. If you try to use git without knowing what’s happening under the hood, you’ll end up confused at some point (unless you stick to only very basic functionality). This may sound stupid when all you want is a DVCS for your daily programming routine, but the genius of git is that the repository format is actually very simple and you can understand git’s entire operation quite easily.

For some more technicality-oriented comparisons, the best articles I have personally seen are Dustin Sallings’:

He has actually used both DVCSs extensively and understands them both well – and ended up preferring git.

51
votes

The big difference is on Windows. Mercurial is supported natively, Git isn't. You can get very similar hosting to github.com with bitbucket.org (actually even better as you get a free private repository). I was using msysGit for a while but moved to Mercurial and been very happy with it.

38
votes

If you are a Windows developer looking for basic disconnected revision control, go with Hg. I found Git to be incomprehensible while Hg was simple and well integrated with the Windows shell. I downloaded Hg and followed this tutorial (hginit.com) - ten minutes later I had a local repo and was back to work on my project.

22
votes

I think the best description about "Mercurial vs. Git" is:

"Git is Wesley Snipes. Mercurial is Denzel Washington"

20
votes

They are almost identical. The most important difference, from my point of view (I mean, the reason that got me to choose one DVCS over the other) is how the two programs manage branches.

To start a new branch, with Mercurial, you simply clone the repository to another directory and start developing. Then, you pull and merge. With git, you have to explicitly give a name to the new topic branch you want to use, then you start coding using the same directory.

In short, each branch in Mercurial needs its own directory; in git you usually work in on single directory. Switching branches in Mercurial means changing directories; in git, it means asking git to change the directory's content with git checkout.

I'm honest: I don't know if it's possible to do the same with Mercurial, but since I usually work on web projects, using always the same directory with git seems much confortable to me, since I don't have to re-configure Apache and restart it and I don't mess my filesystem everytime I branch.

Edit: As Deestan noted, Hg has named branches, which can be stored in a single repository and allow the developer to switch branches within the same working copy. git branches are not exactly the same as Mercurial named branches, anyway: they are permanent and not throw away branches, like in git. That means that if you use a named branch for experimental tasks even if you decide to never merge it it will be stored in the repository. That's the reason why Hg encourages to use clones for experimental, short-running tasks and named branches for long-running tasks, like for release branches.

The reason why a lot of Hg users prefere clones over named branch is much more social or cultural than technical. For example, with last versions of Hg, it's even possible to close a named branch and recursively remove metadata from changesets.

On the other side, git invites to use "named branches" which are not permanent and are not stored as metadata on each changeset.

From my personal point of view, then, git's model is deeply linked to the concept of named branches and switch between a branch and another withing the same directory; hg can do the same with named branches, but yet it encourages the use of clones, which I personally don't like too much.

17
votes

There's one huge difference between git and mercurial; the way the represent each commit. git represents commits as snapshots, while mercurial represents them as diffs.

What does this means in practice? Well, many operations are faster in git, such as switching to another commit, comparing commits, etc. Specially if these commits are far away.

AFAIK there's no advantage of mercurial's approach.

11
votes

Nothing. They both do the same, both perform about equally. The only reason you should choose one over the other is if you help out with a project that already uses one..

The other possible reason for choosing one is an application or service which only supports one of the system.. For example, I pretty much chose to learn git because of github..

11
votes

Also google's comparison (though it's a bit old, done in 2008)

http://code.google.com/p/support/wiki/DVCSAnalysis

11
votes

If I understand them correctly (and I'm far from an expert on each) they fundamentally each have a different philosophy. I first used mercurial for 9 months. Now I've used git for 6.

hg is version control software. It's main goal is to track versions of a piece of software.

git is a time based file system. It's goal is to add another dimension to a file system. Most have files and folders, git adds time. That it happens to work awesome as a VCS is a byproduct of its design.

In hg, there's a history of the entire project it's always trying to maintain. By default I believe hg wants all changes to all objects by all users when pushing and pulling.

In git there's just a pool of objects and these tracking files (branches/heads) that determine which set of those objects represent the tree of files in a particular state. When pushing or pulling git only sends the objects needed for the the particular branches you are pushing or pulling, which is a small subset of all objects.

As far as git is concerned there is no "1 project". You could have 50 projects all in the same repo and git wouldn't care. Each one could be managed separately in the same repo and live fine.

Hg's concept of branches is branches off the main project or branches off branches etc. Git has no such concept. A branch in git is just a state of the tree, everything is a branch in git. Which branch is official, current, or newest has no meaning in git.

I don't know if that made any sense. If I could draw pictures hg might look like this where each commit is a o

             o---o---o
            /        
o---o---o---o---o---o---o---o
         \         /
          o---o---o

A tree with a single root and branches coming off of it. While git can do that and often people use it that way that's not enforced. A git picture, if there is such a thing, could easily look like this

o---o---o---o---o

o---o---o---o
         \
          o---o

o---o---o---o

In fact in some ways it doesn't even make sense to show branches in git.

One thing that is very confusing for the discussion, git and mercurial both have something called a "branch" but they are not remotely the same things. A branch in mercurial comes about when there are conflicts between different repos. A branch in git is apparently similar to a clone in hg. But a clone, while it might give similar behavior is most definitely not the same. Consider me trying these in git vs hg using the chromium repo which is rather large.

$ time git checkout -b some-new-branch
Switched to new branch 'some-new-branch'

real   0m1.759s
user   0m1.596s
sys    0m0.144s

And now in hg using clone

$ time hg clone project/ some-clone/

updating to branch default
29387 files updated, 0 files merged, 0 files removed, 0 files unresolved.
real   0m58.196s
user   0m19.901s
sys    0m8.957

Both of those are hot runs. Ie, I ran them twice and this is the second run. hg clone is the actually the same as git-new-workdir. Both of those make an entirely new working dir almost as though you had typed cp -r project project-clone. That's not the same as making a new branch in git. It's far more heavy weight. If there is true equivalent of git's branching in hg I don't know what it is.

I understand at some level hg and git might be able to do similar things. If so then there is a still a huge difference in the workflow they lead you to. In git, the typical workflow is to create a branch for every feature.

git checkout master
git checkout -b add-2nd-joypad-support
git checkout master
git checkout -b fix-game-save-bug
git checkout master
git checkout -b add-a-star-support

That just created 3 branches, each based off a branch called master. (I'm sure there's some way in git to make those 1 line each instead of 2)

Now to work on one I just do

git checkout fix-game-save-bug

and start working. Commit things, etc. Switching between branches even in a project as big as chrome is nearly instantaneous. I actually don't know how to do that in hg. It's not part of any tutorials I've read.

One other big difference. Git's stage.

Git has this idea of a stage. You can think of it as a hidden folder. When you commit you only commit what's on the stage, not the changes in your working tree. That might sound strange. If you want to commit all the changes in your working tree you'd do git commit -a which adds all the modified files to the stage and then commits them.

What's the point of the stage then? You can easily separate your commits. Imagine you edited joypad.cpp and gamesave.cpp and you want to commit them separately

git add joypad.cpp  // copies to stage
git commit -m "added 2nd joypad support"
git add gamesave.cpp  // copies to stage
git commit -m "fixed game save bug"

Git even has commands to decide which particular lines in the same file you want to copy to the stage so you can split up those commits separately as well. Why would you want to do that? Because as separate commits others can pull only the ones they want or if there was an issue they can revert just the commit that had the issue.

8
votes

There is a dynamic comparison chart over at the versioncontrolblog where you can compare several different version control systems.

Here is a comparison table between git, hg and bzr.

7
votes

There are quite significant differences when it comes to working with branches (especially short-term ones).

It is explained in this article (BranchingExplained) which compares Mercurial with Git.

7
votes

Are there any Windows-based collaborators on your project?

Because if there are, the Git-for-Windows GUI seems awkward, difficult, unfriendly.

Mercurial-on-Windows, by contrast, is a no-brainer.

7
votes

One thing to notice between mercurial of bitbucket.org and git of github is, mercurial can have as many private repositories as you want, but github you have to upgrade to a paid account. So, that's why I go for bitbucket which uses mercurial.

5
votes

Sometime last year I evaluated both git and hg for my own use, and decided to go with hg. I felt it looked like a cleaner solution, and worked better on more platforms at the time. It was mostly a toss-up, though.

More recently, I started using git because of git-svn and the ability to act as a Subversion client. This won me over and I've now switched completely to git. I think it's got a slightly higher learning curve (especially if you need to poke around the insides), but it really is a great system. I'm going to go read those two comparison articles that John posted now.

4
votes

I'm currently in the process of migrating from SVN to a DVCS (while blogging about my findings, my first real blogging effort...), and I've done a bit of research (=googling). As far as I can see you can do most of the things with both packages. It seems like git has a few more or better implemented advanced features, I do feel that the integration with windows is a bit better for mercurial, with TortoiseHg. I know there's Git Cheetah as well (I tried both), but the mercurial solution just feels more robust.

Seeing how they're both open-source (right?) I don't think either will be lacking important features. If something is important, people will ask for it, people will code it.

I think that for common practices, Git and Mercurial are more than sufficient. They both have big projects that use them (Git -> linux kernel, Mercurial -> Mozilla foundation projects, both among others of course), so I don't think either are really lacking something.

That being said, I am interested in what other people say about this, as it would make a great source for my blogging efforts ;-)

4
votes

There is a great and exhaustive comparison tables and charts on git, Mercurial and Bazaar over at InfoQ's guide about DVCS.

3
votes

I realize this isn't a part of the answer, but on that note, I also think the availability of stable plugins for platforms like NetBeans and Eclipse play a part in which tool is a better fit for the task, or rather, which tool is the best fit for "you". That is, unless you really want to do it the CLI-way.

Both Eclipse (and everything based on it) and NetBeans sometimes have issues with remote file systems (such as SSH) and external updates of files; which is yet another reason why you want whatever you choose to work "seamlessly".

I'm trying to answer this question for myself right now too .. and I've boiled down the candidates to Git or Mercurial .. thank you all for providing useful inputs on this topic without going religious.

2
votes

Yet another interesting comparison of mercurial and git: Mercurial vs Git. Main focus is on internals and their influence on branching process.

2
votes

If you are interested in a performance comparison of Mercurial and Git have a look at this article. The conclusion is:

Git and Mercurial both turn in good numbers but make an interesting trade-off between speed and repository size. Mercurial is fast with both adds and modifications, and keeps repository growth under control at the same time. Git is also fast, but its repository grows very quickly with modified files until you repack — and those repacks can be very slow. But the packed repository is much smaller than Mercurial's.

2
votes

The mercurial website has a great description of the similarities and differences between the two systems, explaining the differences of vocabulary and underlying concepts. As a long time git user, it really helped my understand the Mercurial mindset.

2
votes

If you are migrating from SVN, use Mercurial as its syntax is MUCH more understandable for SVN users. Other than that, you can't go wrong with either. But do check GIT tutorial and HGinit before selecting one of them.

1
votes
1
votes

Some people think that VCS systems have to be complicated. They encourage inventing terms and concepts on the field. They would probably think that numerous PhDs on the subject would be interesting. Among those are probably the ones that designed Git.

Mercurial is designed with a different mentality. Developers should not care much about VCS, and they should instead spend their time on their main function: software engineering. Mercurial allows users to use and happily abuse the system without letting them make any non-recoverable mistakes.

Any professional tool must come with a clearly designed and intuitive CLI. Mercurial users can do most of the work by issuing simple commands without any strange options. In Git double dash, crazy options are the norm. Mercurial has a substantial advantage if you are a CLI person (and to be honest, any self-respecting Software Engineer should be).

To give an example, suppose you do a commit by mistake. You forgot to edit some files. To undo you action in Mercurial you simply type:

$ hg rollback

You then get a message that the system undos your last transaction.

In Git you have to type:

$ git reset --soft HEAD^

So ok suppose you have an idea what reset is about. But in addition you have to know what "--soft" and "--hard" resets are (any intuitive guesses?). Oh and of course don't forget the '^' character in the end! (now what in Ritchie's name is that...)

Mercurial's integration with 3rd party tools like kdiff3 and meld is much better as well. Generate your patches merge your branches without much fuss. Mercurial also includes a simple http server that you activate by typing

hg serve

And let others browse your repository.

The bottom line is, Git does what Mercurial does, in a much more complicated way and with a far inferior CLI. Use Git if you want to turn the VCS of your project into a scientific-research field. Use Mercurial if you want to get the VCS job done without caring much about it, and focus on your real tasks.