Question

I have a repository in which two revisions (14321 and 14319) share a parent (14318) - both changesets are direct children of 14318. Nevertheless, the revision set query ancestor(14321, 14319) does not return 14318, but instead returns a much older changeset. What's happening?

Screenshot in TortoiseHg:

A diagram showing the odd results of query ancestor(14321, 14319)

Background: I encountered odd merge conflicts recently that turned out to be caused by mercurial trying to re-apply changes that had already been merged. I was able to track it down to an odd choice of merge base which caused both heads to include the same changes - but I don't understand why this happened and how I can prevent it in the future (I chose a DVCS partly to avoid these kinds of problems in the first place...)

Was it helpful?

Solution

The picture shows there are not one but two common ancestors. So, it looks like a criss-cross merge case where merge problems arise from chosing one or another common ancestor.

References:

There is a proposal for a new merge algorithm (https://www.mercurial-scm.org/wiki/ConsensusMerge). However, since Mercurial's 2.3 sprint this topic is stuck.

To reduce this kind of problem, I suggest you to estabilish a client-server topology, so that developers only merge with the official repository. Maybe rebase could help also.

A criss-cross merge is something like this:

   B --- D
  / \   / \
 /   \ /   \ 
A     X     F 
 \   / \   /
  \ /   \ /
   C --- E

In your case, it was:

           B
-----------o----               } stable/production
      C     \   \       F
------o------o---\------o      } default
       \     D    \    /
        -----------o---        } feature
                   E

A = ?
B = 14318
C = 14294
D = 14319
E = 14321
F = ?

To produce F, there are two possible circuits: B-D-E-F and C-D-E-F. Mercurial has chosen the latter.

You could have avoided the criss-cross if you haven't merged production and feature branches. The hotfix could have been propagated to the feature branch via the default branch. The log would be:

           B
-----------o               } stable/production
      C     \       F
------o------o------o      } default
       \    D \    /
        -------o---        } feature
               E

OTHER TIPS

For incorrect base detection in case of common ancestor of mergesets one weak point is known:

it can be wrong if any of mergesets contains unrelated to merge edit

I guess, that the ancestor is 14294. Since both of your new commits are merges, you now have more than one ancestor, which makes the choice ambiguous.

Unfortunately, there is no way to tell mercurial which of the potential ancestors to use.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top