Backout of a backout and merge

Jilles Tjoelker jilles at stack.nl
Sat Dec 3 15:33:53 CST 2011


On Fri, Dec 02, 2011 at 11:58:18AM +0200, Jouni Airaksinen wrote:
> I suppose I don't understand something from backouts, but we had some 
> trouble with backouts. The core of the situation is such that in default 
> branch we have a change which was merged to another branch. Now this 
> change was backout in the default branch and separately in the second 
> branch where the change was merged (technically the backout was 
> transplanted, but I tested and it doesn't matter if it's done with backout 
> itself). OK, I understand when simplified you could have just merged the 
> backout from default to the another branch, but due customer requests the 
> changes had to be managed individually. 

> So we had now change made in default and backout in both branches the 
> change was appearing. Now later the backout was backout in the default 
> branch to get the change back. Default branch looks fine, but when merging 
> to the another branch (no other merges was done in between) the backout of 
> backout was not merged automatically. This affected normal diff changes 
> and file add/remove operations.

> I was able to test this with plain repository (hg version 
> 1.9+7-308e1b5acc87). Originally in real code it happened with some 
> Mercurial version coming with TortoiseHg (not my workstation).

> Is this correct way of backouts that they are not mergeable or is there 
> something I'm missing on how backout works? It was just little bit WTF 
> when some change was missing after merge. 

This is inherent to the three-way merge algorithm used by Mercurial. The
three-way merge algorithm finds a common ancestor and the result is a
function of the three states of the code. It does not care how those
states were reached.

Graphically:

    |
    A          common ancestor with change
    |
    |\
    | \
    |  \
    |   |
   ~A  ~A      backed out separately in both branches
    |   |
    A   |      back out the backout
    |   /
    |  /
    | /
    |/
   ~A          one side has backed out, other side has done nothing

To avoid this problem (and reduce conflicts), be careful with
transplanting changes between branches that will be merged later (no
matter whether this is using the transplant extension, manually or any
other way). If such a transplant is necessary, merge (in any direction)
sooner rather than later (in the example, an additional merge before
backing out the backout would result in a common ancestor with state ~A
and a correct result in the final merge).

-- 
Jilles Tjoelker


More information about the Mercurial mailing list