I too have been looking for a case where, say, Subversion fails to merge a branch and Mercurial (and Git, Bazaar, …) does the right thing.
The SVN Book describes how renamed files are merged incorrectly. This applies to Subversion 1.5, 1.6, 1.7, and 1.8! I have tried to recreate the situation below:
cd /tmp rm -rf svn-repo svn-checkout svnadmin create svn-repo svn checkout file:///tmp/svn-repo svn-checkout cd svn-checkout mkdir trunk branches echo 'Goodbye, World!' > trunk/hello.txt svn add trunk branches svn commit -m 'Initial import.' svn copy '^/trunk' '^/branches/rename' -m 'Create branch.' svn switch '^/trunk' . echo 'Hello, World!' > hello.txt svn commit -m 'Update on trunk.' svn switch '^/branches/rename' . svn rename hello.txt hello.en.txt svn commit -m 'Rename on branch.' svn switch '^/trunk' . svn merge --reintegrate '^/branches/rename'
According to the book, the merge should finish cleanly, but with wrong data in the renamed file since the update on trunk
is forgotten. Instead I get a tree conflict (this is with Subversion 1.6.17, the newest version in Debian at the time of writing):
--- Merging differences between repository URLs into '.': A hello.en.txt C hello.txt Summary of conflicts: Tree conflicts: 1
There shouldn’t be any conflict at all — the update should be merged into the new name of the file. While Subversion fails, Mercurial handles this correctly:
rm -rf /tmp/hg-repo
hg init /tmp/hg-repo
cd /tmp/hg-repo
echo 'Goodbye, World!' > hello.txt
hg add hello.txt
hg commit -m 'Initial import.'
echo 'Hello, World!' > hello.txt
hg commit -m 'Update.'
hg update 0
hg rename hello.txt hello.en.txt
hg commit -m 'Rename.'
hg merge
Before the merge, the repository looks like this (from hg glog
):
@ changeset: 2:6502899164cc | tag: tip | parent: 0:d08bcebadd9e | user: Martin Geisler | date: Thu Apr 01 12:29:19 2010 +0200 | summary: Rename. | | o changeset: 1:9d06fa155634 |/ user: Martin Geisler | date: Thu Apr 01 12:29:18 2010 +0200 | summary: Update. | o changeset: 0:d08bcebadd9e user: Martin Geisler date: Thu Apr 01 12:29:18 2010 +0200 summary: Initial import.
The output of the merge is:
merging hello.en.txt and hello.txt to hello.en.txt 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)
In other words: Mercurial took the change from revision 1 and merged it into the new file name from revision 2 (hello.en.txt
). Handling this case is of course essential in order to support refactoring and refactoring is exactly the kind of thing you will want to do on a branch.