From my understanding SVN is 'Easy to branch. Difficult to merge'. Why is that? Is there a difference how they merge?
|
|
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:
He also raises some good points about the differences:
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. |
|||||||||
|
|
The core problem lies in the way these systems represent a versioned directory structure. Subversion's basic concept around which the whole system revolves is that of a version (or, in svn lingo, "revision"): a snapshot of a file at a certain point. As long as the history is perfectly linear, all is fine, but if you need to merge changes from two independent lines of development, svn has to compare the current versions of both, and then do a three-way comparison between the last shared version and the two head versions. Lines that appear changed in one of the heads, but not the other, can easily be resolved; lines that deviate exactly the same way in both heads are harder, but usually doable; lines that deviate in different ways are what makes svn say "I can't figure this out, human, please resolve this for me." By contrast, git and mercurial track changesets rather than versions. The entire repository is a tree of changesets, each one depending on a parent, where a parent changeset can have any number of children, and the tree root represent an empty directory. In other words, git/hg says "first I had nothing, then this patch was applied, then that patch, etc.". When you need to merge two lines of development, git/hg not only knows what each head currently looks like, and what the last common version looked like, it also knows how the transition happened, allowing for much smarter merging. Another thing that makes merging easier in a DVCS is an indirect consequence of separating the concepts of commit and push, and of allowing all sorts of cross-merges between any two clones of the same repository at any time. With svn, people tend to commit large changesets with often unrelated changes, because a commit is also an update on the central repository which affects all other team members; if you commit a broken version, everyone is going to be angry with you. Since most setups involve a networked svn server, committing also involves pumping data over the network, which means committing introduces a considerable delay to the workflow (especially when your working copy is outdated and you have to pull first). With git and mercurial, the commit happens locally, and because both are very efficient at handling local filesystems, it usually finishes instantly. As a result, people (once they get used to it) commit small incremental changes, and then when it works, push a dozen or so commits in one go. Then when merge time comes around, the SCM has much more detailed information to go by, and can do a better job resolving conflicts safely and automatically. And then there's the nice details that make things even easier:
|
|||||||||||||||||
|