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.