This I don't get. The branching/merging thing seems to be overblown to me.
The reason I'm switching is because I like the tools better, and you can be up and running with a repo in about 5 seconds. I think that's argument enough. There's less pain.
But what is so different about merging in hg/git that merging a complex change from a branch is somehow made magically trivial? I mean, the tools for handling changes might be better because they are more modern, but the whole "changeset" thing seems to be hyperbole -- all (well, any good one) VCS's track changesets, that's what those revision numbers (or collectison of rev numbers) mean. :-)
I understand where you are coming from. I used to think the same way. But once you have used git or Mercurial with their powerful branching/merging capabilities, you will never go back to anything else. Also, it's not that the tools aren't better, it's that git and Mercurial have different architecture which makes branching/merging easy and powerful. I would sincerely request you to not dismiss this 'branch/merge' phenomena. Once you understand their power, you would wonder why you ever managed to live with Subversion (or other centralized VCS).
Searching on Google, I came across this example which will show you how powerful Git really is. [warning: PDF link]
Oh the branching and merging can be big problems for some of us :-)
The difference is that hg preserves the local commits as part of the upstream commit-set. That gives it a lot of information when making decisions about merging. SVN only has two versions of the file: what's in the server and yours. There's just less information to merge intelligently.
Joel hits on this on the first page (Subversion Re-education). My understanding, as a DVCS virgin, is that you commit far more often (to your local repository) than with Subversion, and so Hg can more intelligently merge things.
My guess is that there is some intelligence that can tell that "foo missing there, and foo added here" is actually just "foo moved from there to here", unlike SVN, which attempts no such heuristics. I hope someone can correct me if I'm wrong here :)
The difference is that SVN is dumb on a profound level when it comes to diffing. It knows how to diff one file vs. another, and that works great for incremental changes all in one branch, but it doesn't keep track of revision and merge history the way more modern tools like perforce, TFS, and especially git and mercurial do.
The end result is that when you have two branches that have become even a little out of sync with each other when you try to merge them together SVN doesn't know what to do because all it can do is diff one version against the other. Imagine how this looks if you've spent a bunch of time refactoring in one branch, moving code around, deleting code, adding new code, etc. The end result is that you basically have to hand-edit each file into the final merge state you need it to be in, entirely defeating the very reason you use source control tooling in the first place. You might as well just print out all the code from each branch and get a committee to merge it all together using scissors and craft glue, it wouldn't take any longer or be any more onerous than it would be using SVN.
In contrast, more sophisticated VCSes, including hg, keep track of changesets, and they are capable of tracking those changesets as they move through different branches. When you merge in Mercurial it's able to trace through the revision history of a file in the source and target branches, find the common revision, then separately apply the diffs from the source and target branches, automatically check for conflicts (e.g. changes from both sides that touch the same blocks of code) and create a sanely merged final result which will only be flagged as a merge conflict requiring manual intervention when there's a high probability that there actually is a merge conflict. More so, the merge conflict will be presented in such a way that it's actually sensible, showing the actual conflicting changes and the resulting conflicting final versions of the file, making it fairly straightforward to resolve even in that case.
Casting this in the form of a real world example, consider a "main" branch with two dev. teams each working in their own child branches. For the most part each dev. team works on their own code within their own set of files, separate from the other team's, but there is some common code which both teams have a tendency to contribute to or change. Team A spends a bunch of time making changes in their own branch (branch A), committing as they go, then merges these changes up to main. Later team B merges their changes to main as well. Instead of running into a merge conflict nightmare that requires huge amounts of developer time be expended in sorting out the state of each and every file, the version control system sees that team B hasn't made any changes to most of the files in the repository, and most of the changes team B has made are to files that haven't been changed by anyone else, and there are only a tiny number of changes to files that had also been changed by team A's recent commits, which hadn't been merged to team B's branch before team A pushed their code up to main. However, most of those edits are to distinctly different parts of the shared files, and are automatically merged without human intervention, only a tiny handful of merges require manual intervention, a process that takes only a tiny number of people a few minutes to sort out. Some of those automated merges may, in theory, not be safe, but that is what testing is for, and the devs can still review and sanity check the merged files before committing if they like.
The ability to turn a show-stopping ordeal into a routine task can be utterly transformative to the development process. There are many big dev. shops that are reliant on dozens or perhaps hundreds of big merges (in multi-thousand file code bases) shuffling around code between various branches every day.
When you merge in Mercurial it's able to trace through the revision history of a file in the source and target branches, find the common revision, then separately apply the diffs from the source and target branches...
Originally subversion couldn't do this, but it has had merge tracking since version 1.5 (a couple of years already). You can now merge one branch into another multiple times without specifying explicitly which revisions to compare.
I have seen a number of people saying that the merge tracking in subversion still isn't as good as what's in git or mercurial, but I haven't found an explanation of the difference. Can someone elaborate, or point me to some good reading?
lallysingh and nollidge point out that in a DVCS model you tend to make more frequent commits, because committing and publishing are no longer the same action, and that having finer-grained commits makes automatic merging more likely to succeed. This seems quite plausible to me, but it's orthogonal to the problem of merge tracking (isn't it?).
The reason I'm switching is because I like the tools better, and you can be up and running with a repo in about 5 seconds. I think that's argument enough. There's less pain.
But what is so different about merging in hg/git that merging a complex change from a branch is somehow made magically trivial? I mean, the tools for handling changes might be better because they are more modern, but the whole "changeset" thing seems to be hyperbole -- all (well, any good one) VCS's track changesets, that's what those revision numbers (or collectison of rev numbers) mean. :-)