Version Control – Differences Between Merges in SVN, Git, and Mercurial

dvcsgitmercurialsvn

From my understanding SVN is 'Easy to branch. Difficult to merge'. Why is that? Is there a difference how they merge?

Best Answer

Please see my Stack Overflow answer for a very concrete situation where Mercurial (and Git) merges without problems and where Subversion presents you with a bogus conflict. The situation is a simple refactoring done on a branch where you rename some files.

With regard to tdammers answer, then there is a number of misunderstandings there:

  • Subversion, Mercurial, and Git all track repository-wide snapshots of the project. Calling them versions, revisions, or changesets makes no difference. They are all logically atomic snapshots of a set of files.

  • The size of your commits makes no difference when it comes to merging. All three systems merge with the standard three-way merge algorithm and the inputs to that algorithm are

    • greatest common ancestor version
    • version on one branch
    • version on other branch

    It doesn't matter how the two branch versions were created. You can have used 1000 small commits since the ancestor version, or you can have used 1 commit. All that matters is the final version of the files. (Yes, this is surprising! Yes, lots of DVCS guides get this horribly wrong.)

He also raises some good points about the differences:

  • Subversion has some "voodoo" where you can merge from /trunk into, say, /branches/foo. Mercurial and Git does not use this model — branches are instead modeled directly in the history. The history therefore becomes a directed acyclic graph instead of being linear. This a much simpler model than the one used by Subversion and this cuts away a number of corner cases.

  • You can easily delay a merge or even let someone else handle it. If hg merge gives you a ton of conflicts, then you can ask your coworker to hg pull from you and then he has the exact same state. So he can hg merge and maybe he's better at resolving conflicts than you are.

    This is very difficult with Subversion where you're required to update before you can commit. You cannot just ignore the changes on the server and keep committing on your own anonymous branch. In general, Subversion forces you to play around with a dirty working copy when you svn update. This is kind of risky since you haven't stored your changes anywhere safe. Git and Mercurial lets you commit first, and then update and merge as necessary.

The real reason Git and Mercurial are better at merging than Subversion is a matter of implementation. There are rename conflicts that Subversion simply cannot handle even thought it's clear what the correct answer is. Mercurial and Git handles those easily. But there's no reason why Subversion couldn't handle those as well — being centralized is certainly not the reason.

Related Topic