Tutorial - Merging conflicting changes
(This page is part 8 of 9 of the [:Tutorial] series. Previous part is [:TutorialMerge], next part is [:TutorialConclusion])
We learned how to deal with simple [:Merge:merges] in TutorialMerge.
Mercurial handles more complex merge cases, too. It is not all that uncommon for two people to edit the exact same lines of a file, and then have to figure out what to do. These cases are called [:Conflict:conflicts]; figuring out what to do about a conflict is called [:ResolveConflict:resolving] it.
Let's first create an artificial conflict situation. As we did previously, let's start by making a [:Clone:clone] of my-hello:
$ cd .. $ hg clone my-hello my-hello-not-cvs updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
Now let's add a new line of output to hello.c:
$ cd my-hello-not-cvs $ vi hello.c
We change main to read like this:
int main(int argc, char **argv)
{
printf("hello, world!\n");
printf("sure am glad I'm not using CVS!\n");
return 0;
}
And we [:Commit:commit] the change:
$ hg commit -m "Give thanks for dodging bullet"
Recall that in TutorialFirstChange, we created a [:ChangeSet:changeset] in my-hello-new-output that also added a second line of output. What happens when we try to [:Pull:pull] that change in here?
$ hg pull ../my-hello-new-output pulling from ../my-hello-new-output searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge)
So far, so good. Let's try an [:Update:update].
$ hg update abort: crosses branches (use 'hg merge' or 'hg update -C')
As in [:TutorialMerge], we have to run hg merge. It will not be able to merge automatically, because the same line of the same source file has been modified in a different way by each changeset (the one we just [:Commit:commited], and the one we just pulled).
$ hg merge
At this point, what happens depends on how Mercurial is configured (see [:MergeToolConfiguration]). Per default, Mercurial drops into the editor marking the conflicts in the file for manual resolution:
/* * hello.c * * Placed in the public domain by Bryan O'Sullivan * * This program is not covered by patents in the United States or other * countries. */ #include <stdio.h> int main(int argc, char **argv) { printf("hello, world!\n"); <<<<<<< /home/adi/tmp/tutorial/my-hello-not-cvs/hello.c printf("sure am glad I'm not using CVS!\n"); ======= printf("sure am glad I'm using Mercurial!\n"); >>>>>>> /tmp/hello.c~other.2xAVqv return 0; }
In the editor, we delete the conflict markers and keep the "sure am glad I'm using Mercurial!\n" line, deleting the line about CVS. When we leave the editor, Mercurial asks:
Was the merge successful? [y/n]
Here, we answer "y". Mercurial now reports the summary of the manual merge process:
0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)
As before, be sure to commit this change to the repository once the merge is complete:
$ hg commit -m "Merged changes from my-hello-new-output"
What we have seen here is the default behaviour of Mercurial. However, Mercurial can be configured to call external three-way merge tools. Information about configuring three-way merge tools can be found at [:MergeToolConfiguration].
Now let's continue and finish on to [:TutorialConclusion].