How to graft a merge changeset with Mercurial
Asked Answered
H

2

9

I would like to graft a merge changeset:

$ hg graft -UD --log -r 1909
skipping ungraftable merge revision 1909

My workaround is:

 hg export -r 1909 | hg import - 
 hg commit -m"$(hg log -r 1909 --template 'grafted {node}')"

Is there a reason that grafting a merge changeset is not supported?

Howlond answered 31/5, 2013 at 9:2 Comment(0)
S
5

Starting with Mercurial release 4.9 command hg graft has a --base option that you can use for this purpose.
Its usage is explained in hg graft documentation page:

--base can be used to specify another ancestor than the first and only parent.

 

The result of a merge can thus be backported as a single commit by specifying one of the merge parents as base

With your example, if you want to graft the changes relatively to parent revision 1908, you can use this command:

hg graft -r 1909 --base 1908
Steels answered 31/1, 2020 at 5:13 Comment(1)
And of course the obvious question is, why does hg export work, and why don't you have to specify a --base commit there?Kenyakenyatta
O
4

Merge changesets have two parents and therefore two different ways of looking at what changed. By default if you use hg diff -c <changeset> it will show the diff as compared to the first parent which typically represented the working directory at the time of the merge. If that assumption is wrong, it is an easy way to introduce errors.

That leads to the question of why you are grafting a merge change set and not the original changeset(s) themselves. If there are a series of changesets you want to graft and you are using the merge changeset to "rollup" that series, you can graft the original multiple changes at once: hg graft "1000::1005".

Personally, I typically use hg rebase for tasks such as this, though that requires enabling the rebase extension in your hgrc or mercurial.ini:

[extensions]
rebase=
Original answered 31/5, 2013 at 17:14 Comment(3)
The motivation is that grafting the merge changeset is easier than merging the grafting individual changesets. There are also situations where grafting individual changesets from the second branch is not obvious. In my case rebase is not applicable. The changesets are already public.Howlond
I have a merge where there were difficult-to-resolve merge conflicts. I want to know how to graft that merge changeset back because the resolution would work against an older p1() instead of redoing the work of the merge conflict resolution, but sounds like that’s not an option.Succumb
Another solution is to go to a revision just before the merge, revert all files to the state after the merge, commit (perhaps in a separate branch; you can also - to be sure - merge the original revision to this branch to make sure that this results in no change), then graft the resulting commit.Wirewove

© 2022 - 2024 — McMap. All rights reserved.