Bug 3984 - Merge with ambiguous ancestor does the wrong thing
Summary: Merge with ambiguous ancestor does the wrong thing
Status: VERIFIED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: 2.6
Hardware: PC Linux
: critical bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-07-16 17:38 UTC by Tavis Elliott
Modified: 2013-07-30 13:37 UTC (History)
6 users (show)

See Also:
Python Version: ---


Attachments
Output of "hg debugdag" with mercurial 2.6 (25.66 KB, text/plain)
2013-07-17 12:05 UTC, Tavis Elliott
Details
Example repository that exhibits the ancestor issue (3.83 KB, application/octet-stream)
2013-07-17 13:14 UTC, Tavis Elliott
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tavis Elliott 2013-07-16 17:38 UTC
(I don't _think_ this is the same thing as 1327, but correct me if I'm wrong)

Mercurial version 2.6 (+ AFAIK, we tested with 2.6.0, 2.6.1, and 2.6.2) cannot determine the common ancestor, whereas 2.2.2 and 2.4.2 can.

For the repro steps below, the following is the result in 2.2.2:
> hg log -r "ancestor(I, J)"
changeset: D
parent:    B

> hg up I
> hg merge J

Does exactly what we want it to.  Causes the changes in J to be merged into default.

In 2.6.x, the log command does nothing, and the attempt to merge causes 22 thousand files (that were deleted or have been moved) to be re-added to the repository in default.

Repro steps for the last time this occurred:
--------------------------------------------
(I can come up with a simple repository with changesets that exhibits the problem, but it's too much work I don't have time for right now)

- Have a repository with a bunch of changes, two branches (foo, default).
- Ensure the branches are merged together at some point.  I'll assume the following initial state for the example:

default:      A ---+ C  (Merge of B and A)
foo branch:   B --/

Person 1:  
1. Make a change to foo branch (D)
2. Merge that change to default (E)

default:      A ---+ C ----+ E 
foo branch:   B --/-- D --/


Person 2:  (Have NOT pulled 1's changes yet)
1. Make a change to foo branch (F)
2. Merge that change to default (G)
3. Try to push.  Ooops, multiple heads!  Pull person 1's changes.
4. Merge B & D on Foo (H)
5. Merge C and E on default (I)

default:      A -----+ C ---+ G --+ I
                    /      /  E -/
                   /      /
foo branch:   B --/-- F ----+ H
                      D ---/

(Note that person 2 did NOT merge H and I into default.  Bad person 2!  Even though it's no-op, they should have done it)

Person 3:  (Up to date with all of the above)
1. Make a change to foo branch (J)
2. Merge that change to default (K)

default:      I -------+ K
foo branch:   H -- J -/

*** This merge into K does the WRONG thing, it adds 22 thousand files back to the
repository.
Comment 1 Tavis Elliott 2013-07-16 17:44 UTC
I should also mention that in 2.6.x

> hg merge --debug J 

shows in the output:

resolving manifests
 branchmerge: True, force: False, partial: False
 ancestor: 000000000000, 
<snip>
Comment 2 Matt Mackall 2013-07-16 17:45 UTC
What revision does this report?

hg log -r 'heads(::I and ::J)'
Comment 3 Tavis Elliott 2013-07-16 18:03 UTC
Both 2.2.2 and 2.6.2 report:

changeset:   D
branch:      foo
parent:      B
user:        Person 1

changeset:   F
branch:      foo
parent:      B
user:        Person 2
Comment 4 Matt Mackall 2013-07-17 11:09 UTC
Please send the output of 'hg debugdag' as well as the revision numbers of A-J.
Comment 5 Tavis Elliott 2013-07-17 12:05 UTC
Created attachment 1731 [details]
Output of "hg debugdag" with mercurial 2.6

Output attached.

A - 6127297ac5dd
B - 8938d18d6891

D - 3b438241dee4
E - ea3fc3e156b9
F - 97a721406092
G - 1372f4bb9f51
H - e3caa97969a2
I - 18f41973cf54
J - 1581637101c6

Looks like my repository pre-condition in the description was slightly incorrect.  :(  There wasn't a merge of A & B into C before the rest of the flow.

Updated:

Person 1:

default:      A -----------+ E 
foo branch:   B ----- D --/

Person 2:
default:      A ------------+ G --+ I
                           /  E -/
                          /
foo branch:   B ----- F ----+ H
                      D ---/
Comment 6 Tavis Elliott 2013-07-17 13:14 UTC
Created attachment 1732 [details]
Example repository that exhibits the ancestor issue

I have created an example repository that simulates what we have in our repository.

> tar -xzf example.tar.gz
> cd 3984_merge
> hg log -r "ancestor(10,9)"

2.2.2 result:
> hg log -r "ancestor(10,9)"
changeset:   4:f303d6efbf44
branch:      foo
parent:      2:d0f226159ee1
user:        Tavis Elliott <telliott@apptio.com>
date:        Wed Jul 17 09:11:23 2013 -0700
summary:     Added e, modified c

>

2.6.2 result:
> hg log -r "ancestor(10,9)"
>

As an additional oddity, when I actually perform the merge in this example, both versions report f as "M" when I would have expected it to be reported as "A".

> hg st
M a
M f

2.2.2 merge --debug:
> hg merge --debug foo
  searching for copies back to rev 3
  unmatched files in other:
   f
resolving manifests
 overwrite: False, partial: False
 ancestor: f303d6efbf44, local: acb2772e6d17+, remote: f556490bce43
 a: remote is newer -> g
 f: remote created -> g
updating: a 1/2 files (50.00%)
getting a
updating: f 2/2 files (100.00%)
getting f
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)


2.6.2 merge --debug:
> hg merge --debug foo
resolving manifests
 branchmerge: True, force: False, partial: False
 ancestor: 000000000000, local: acb2772e6d17+, remote: f556490bce43
 a: versions differ -> m
  preserving a for resolve of a
 f: remote created -> g
getting f
updating: f 1/2 files (50.00%)
updating: a 2/2 files (100.00%)
couldn't find merge tool codecompare_diff
couldn't find merge tool codecompare_merge
couldn't find merge tool filemerge
couldn't find merge tool gpyfm
couldn't find merge tool bcompare
couldn't find merge tool beyondcompare3-noauto
couldn't find merge tool rekisa
couldn't find merge tool UltraCompare
couldn't find merge tool araxis
couldn't find merge tool beyondcompare3
picked tool 'meld' for a (binary False symlink False)
merging a
my a@acb2772e6d17+ other a@f556490bce43 ancestor a@81f09d5a96fc
 premerge successful
1 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
Comment 7 Tavis Elliott 2013-07-18 11:51 UTC
Until this bug gets fixed, we're going to have to figure out how to revert the entire org to 2.2.2 (there don't seem to be any ppg available other than 2.2.2 and 2.6.x for ubuntu, etc)
Comment 8 Matt Mackall 2013-07-18 15:13 UTC
Raising this to critical. We should have a fix for this shortly.
Comment 9 Jay G 2013-07-26 02:14 UTC
Is there an ETA on the fix for this? Thank you!
Comment 10 Siddharth Agarwal 2013-07-26 02:43 UTC
A patchset fixing this has been sent to the mailing list.
Comment 11 Matt Mackall 2013-07-26 14:10 UTC
The next release is August 1st, and this should be fixed in that release.
Comment 12 HG Bot 2013-07-26 15:15 UTC
Fixed by http://selenic.com/repo/hg/rev/f2dfda6ac152
Wei, Elson <elson.wei@gmail.com>
ancestor.deepest: decrement ninteresting correctly (issue3984)

The invariant this code tries to hold is that ninteresting is the number of
non-zero elements in the interesting array. interesting[nsp] is incremented at
the same time as interesting[sp] is decremented. So if interesting[nsp] was
previously 0, ninteresting shouldn't be decremented.

(please test the fix)
Comment 13 HG Bot 2013-07-26 15:15 UTC
Fixed by http://selenic.com/repo/hg/rev/2fa303619b4d
Siddharth Agarwal <sid0@fb.com>
ancestor.deepest: ignore ninteresting while building result (issue3984)

ninteresting indicates the number of non-zero elements in the interesting
array, not the number of elements in the final list. Since elements in
interesting can stand for more than one gca, limiting the number of results to
ninteresting is an error.

Tests for issue3984 are included.

(please test the fix)
Comment 14 Tavis Elliott 2013-07-30 13:37 UTC
Verified this fixed the test case, AND the latest (version 2.7-rc+5-ca2dfc2f63eb) also fixed the problem in the actual full repository.