3

I created a new repository, test-backout, and added a new file in it, file. I then made 4 commits, each time, appending the number of the commit to file using

echo [manually entered number] >> file
hg commit -m '[manually entered number]'

In effect, file had:

init
1
2
3

According to the hg book, if I run hg backout --merge 2, I should have:

init
1
3

but instead, it fails to merge and opens up my difftool (vimdiff), and I get 3 options:

init          | init          | init
1             | 1             |
2             |               |
3             |               |

I initially tried it with the --merge option, then again without it. My question now is, is there still a way for me to get:

init
1
3

did I just make a mistake or miss something, or am I stuck with those options?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
cesar
  • 8,944
  • 12
  • 46
  • 59

1 Answers1

7

A big factor in why you got the 3-way merge is that your context is too artificial, and I will get to that.

If I take a 50-line text file and change a different part and commit each change, I won't have to resolve conflicts. And what I mean is I have 4 changesets: rev 0 adds the file, revs 1, 2, and 3 each change one area of the file: the beginning, middle, or end.

In this situation, when I do hg backout 2, it makes a reverse of rev 2 and merges those changes to my working directory, and when I commit, the graph is linear:

@  backout 2
|
o  3
|
o  2
|
o  1
|
o  initial

If I instead do hg backout 2 --merge, it automatically commits the backout as a child of the revision it is backing out, and then merges that with the tip, producing a branched graph after I commit the merge:

@    merge
|\
| o  backout 2
| |
o |  3
|/
o    2
|    
o    1
|    
o    initial

In both situations, I didn't have to do any 3-way merging. The reason you don't automatically get

init
1
3

and instead have to do a 3-way merge is that the changes are too close together. The context and changes in each changeset are completely overlapped (default number of lines of context for a diff chunk is 3 lines, which encompasses the entire file still in your 4th changeset).

A similar example is if you had 3 changesets that each modified the same line. If you backed out the middle change like you're doing here, you would still be presented with a 3-way merge that you'll likely have to manually edit to get correct.

By the way, behavior did change in 1.7, as attested by hg help backout:

Before version 1.7, the behavior without --merge was equivalent to specifying --merge followed by "hg update --clean ." to cancel the merge and leave the child of REV as a head to be merged separately.

However, I don't think that's quite what you suspected.

Joel B Fant
  • 24,406
  • 4
  • 66
  • 67
  • If I made the test text longer, i.e. using `Lorem ipsum`, would that make it work? Also, just as a clarification, is there a difference in the output when using `--merge`, or are both outputs `tip - rev2`, where `tip` is the set of all revisions up to the tip, and `rev2` is the set of all revisions that were removed by `hg backout`? – cesar Aug 17 '11 at 06:25
  • @anonymous: Making the text longer like that won't make a difference. The diff (and hence the resulting merge) is done on "chunks" of lines, not characters. Your example may work if you echo'd several (>6) blank lines after the number - this may result in each addition to the file being recorded as a separate diff "chunk", making the backout merge much easier. – icabod Aug 17 '11 at 07:55
  • Also, +1 to Joel for mentioning diff chunks. – icabod Aug 17 '11 at 07:55
  • @anon: To put it another way -- If you make the text longer and any changes after the revision you're backing out are still very close to any changes in the backout, there is a good change you'll have to manually merge. Results are the same with/without `--merge`, just structured differently. But I want to clarify that backout doesn't *remove* anything. It *adds* changes that do the opposite of the revision you're backing out, changing things back to the way they were before that revision (then merging that with later changes). – Joel B Fant Aug 17 '11 at 14:07