I've been using Mercurial for a while, and there's one "fact" that is given many times.
In fact, it hit me while watching a video made by Fogcreek yesterday, this video: Fog Creek Kiln: Unlock the power of DVCS for your company that there seems to be something that doesn't work for me here.
At around 1:39 in that video and onwards it makes a point of saying that while other version control systems tracks revisions (ie. snapshots), DVCS' like Mercurial track changesets (ie. what happened between the snapshots.)
This gives them an edge in merging scenarios, and then it shows an example. If you move a function in one branch, and change the same function in another branch, Mercurial is able to merge that.
And I've seen this mentioned elsewhere, though I can't find any direct links now.
This doesn't seem to work for me.
Edit: This is a problem with the default "beyondcompare3" merge tool configuration for TortoiseHg. I added the configuration below to my Mercurial.ini file, and now it works as expected. Sure, it'll punt to the GUI tool if it can't automerge, but now the merge described in this question here runs without any prompts and just does the right thing out of the box
[ui]
merge = bc3
[merge-tools]
bc3.executable = C:\Program Files (x86)\Beyond Compare 3\bcomp.exe
bc3.args = $local $other $base $output /automerge /reviewconflicts /closescript
bc3.priority = 1
bc3.premerge = True
bc3.gui = True
To test this, I committed this file to a repository:
void Main()
{
Function1();
Function2();
}
public void Function1()
{
Debug.WriteLine("Function 1");
for (int index = 0; index < 10; index++)
Debug.WriteLine("f1: " + index);
}
public void Function2()
{
Debug.WriteLine("Function 1");
}
Then in two different parallel changesets branching out from this one, I did the following two changes:
- I moved the Function1 function to the bottom of the file
- I changed the message inside Function1
I then tried to merge, and Mercurial gives me a merge conflict window, trying to figure out what I did.
Basically, it tries to change the text in Function2, which is now in the position that Function1 was before it was moved.
This was not supposed to happen!
Here's the source files for reproducing my example:
Batch file for producing repository:
@echo off
setlocal
if exist repo rd /s /q repo
hg init repo
cd repo
copy ..\example1.linq example.linq
hg commit -m "initial commit" --addremove --user "Bob" --date "2010-01-01 18:00:00"
copy ..\example2.linq example.linq
hg commit -m "moved function" --user "Bob" --date "2010-01-01 19:00:00"
hg update 0
copy ..\example3.linq example.linq
hg commit -m "moved function" --user "Alice" --date "2010-01-01 20:00:00"
The 3 versions of the file, example1.linq, example2.linq and example3.linq:
Example1.linq:
<Query Kind="Program" />
void Main()
{
Function1();
Function2();
}
public void Function1()
{
Debug.WriteLine("Function 1");
for (int index = 0; index < 10; index++)
Debug.WriteLine("f1: " + index);
}
public void Function2()
{
Debug.WriteLine("Function 1");
}
Example2.linq:
<Query Kind="Program" />
void Main()
{
Function1();
Function2();
}
public void Function2()
{
Debug.WriteLine("Function 1");
}
public void Function1()
{
Debug.WriteLine("Function 1");
for (int index = 0; index < 10; index++)
Debug.WriteLine("f1: " + index);
}
Example3.linq:
<Query Kind="Program" />
void Main()
{
Function1();
Function2();
}
public void Function1()
{
Debug.WriteLine("Function 1b");
for (int index = 0; index < 10; index++)
Debug.WriteLine("f1: " + index);
}
public void Function2()
{
Debug.WriteLine("Function 1");
}