Mercurial_ The Definitive Guide - Bryan O'Sullivan [36]
It is helpful to remember that the hg revert command is useful for changes that you have not yet committed. Once you’ve committed a change and then decide it was a mistake, you can still do something about it, though your options may be more limited.
For more information about the hg revert command, and details about how to deal with changes you have already committed, see Chapter 9.
Dealing with Tricky Merges
In a complicated or large project, it’s not unusual for a merge of two changesets to result in some headaches. Suppose there’s a big source file that’s been extensively edited by each side of a merge: this is almost inevitably going to result in conflicts, some of which can take a few tries to sort out.
Let’s develop a simple case of this and see how to deal with it. We’ll start off with a repository containing one file, and clone it twice.
$ hg init conflict
$ cd conflict
$ echo first > myfile.txt
$ hg ci -A -m first
adding myfile.txt
$ cd ..
$ hg clone conflict left
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg clone conflict right
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
In one clone, we’ll modify the file in one way.
$ cd left
$ echo left >> myfile.txt
$ hg ci -m left
In another, we’ll modify the file differently.
$ cd ../right
$ echo right >> myfile.txt
$ hg ci -m right
Next, we’ll pull each set of changes into our original repo.
$ cd ../conflict
$ hg pull -u ../left
pulling from ../left
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg pull -u ../right
pulling from ../right
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
not updating, since new heads added
(run 'hg heads' to see heads, 'hg merge' to merge)
We expect our repository to now contain two heads.
$ hg heads
changeset: 2:ef015a2d8ff7
tag: tip
parent: 0:7795ddfbad20
user: Bryan O'Sullivan date: Tue May 05 06:44:30 2009 +0000 summary: right changeset: 1:9c07968fae18 user: Bryan O'Sullivan date: Tue May 05 06:44:30 2009 +0000 summary: left Normally, if we run hg merge at this point, it will drop us into a GUI that will let us manually resolve the conflicting edits to myfile.txt. However, to simplify things for presentation here, we’d like the merge to fail immediately instead. Here’s one way we can do so. $ export HGMERGE=merge We’ve told Mercurial’s merge machinery to run the command false (which, as we desire, fails immediately) if it detects a merge that it can’t sort out automatically. If we now fire up hg merge, it should grind to a halt and report a failure. $ hg merge merging myfile.txt merge: warning: conflicts during merge merging myfile.txt failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges Even if we don’t notice that the merge failed, Mercurial will prevent us from accidentally committing the result of a failed merge. $ hg commit -m 'Attempt to commit a failed merge' abort: unresolved merge conflicts (see hg resolve) When hg commit fails in this case, it suggests that we use the unfamiliar hg resolve command. As usual, hg help resolve will print a helpful synopsis. File Resolution States When a merge occurs, most files will usually remain unmodified. For each file where Mercurial has to do something, it tracks the state of the file: A resolved