Merging two branches without actually merging

Gilles Moris gilles.moris at free.fr
Mon Jan 31 02:31:34 CST 2011


On Sunday 30 January 2011 01:35:25 pm kostolma lokmit wrote:
> Hello,
>
> This looks like a fairly common and straightforward requirement, but I've
> looked into transplant extension, rebase, import, export, etc, and I have
> yet to figure it out. Hopefully I am missing out something obvious.
> I would like to "merge" two branches (named branches, to be specific) such
> that the branches themselves don't go away. Essentially, I want to pull
> changes from a  revision but manually resolve cherrypick changes/conflicts
> (using my merge program).
>
> It seems that import, export, transplant, etc generate patches and
> changesets that are directly applied to the current working directory. But
> I don't want that... instead, I want to manually determine what changes go
> in.
>
> Appreciate your help.

Do you mean that you want to select changeset by changeset when merging a 
branch, which goes in or not ?

In this case, there is no automated tool that will provide you that. Possible 
solutions are:

1a/ As explained in other replies, you can merge the whole thing, and then 
sort out file by file what you want and don't want. You may try to reverse 
patch from the merge the changeset X you don't want doing
cvs diff -c X | patch -p1 -R
But it case of patch conflicts, that may be painful.
This is basically Mike's solution.

1b/ Same as above but use "hg backout" instead of "patch -R". Pros: it will 
merge those reverse patches with a GUI tool in case of conflicts. Cons: I 
guess you will have to commit the merge first, then undo the revision you 
don't want with backout subsequently one by one (not sure of that).

2/ transplant has many different mode and a --merge option which might help 
you. I don't know transplant enough to help you as I don't use it (and to be 
fair, don't like it)

3/ Replace the big merge by a sequence of real and dummy merge[*].
Suppose you have 2 branches BA and BB and you want only merge the Y's of BB 
into  BA:

A-> BA
 \
  +--Y1--Y2--Y3--N4--N5--Y6--Y7-> BB

You would first merge the first series of Y's, resolve the conflicts and 
commit this first merge:
hg update BA
hg merge Y3
hg commit -m "merge Y1 to Y3 into BA"

You would be there:

A-------------M1-> BA
 \            /
  +--Y1--Y2--Y3--N4--N5--Y6--Y7-> BB

Then dummy merge (throw out) the sequence of N's:

hg merge N5
hg revert --all
hg commit -m "throw out N4 to N5 for branch BA"

A-------------M1------D2-> BA
 \            /       /
  +--Y1--Y2--Y3--N4--N5--Y6--Y7-> BB

Then the Y's again:
hg merge Y7
hg commit -m "merge Y6 to Y7 into BA"

A-------------M1------D2------M3-> BA
 \            /       /       /
  +--Y1--Y2--Y3--N4--N5--Y6--Y7-> BB

So your BA branch will contain a sequence of real and dummy merge.
It will work best if you merge often, as this will decrease the overhead.
Its better as it keeps track in the history what you keep and what you 
discard.

Regards.
Gilles.

[*] 
http://mercurial.selenic.com/wiki/TipsAndTricks?highlight=%28dummy%29#Keep_.22My.22_or_.22Their.22_files_when_doing_a_merge
See also Subsume extension https://bitbucket.org/parren/hg-subsume/overview


More information about the Mercurial mailing list