11

We have two heads. One is our main development head and the other is one that I forgot about until today. We found a bug and fixed it in our main development branch, and I just realized it should be fixed in the older branch as well.

I think it would have been better to make the change on the older branch and merge that with the up-to-date branch, but we didn't do it that way. Can mercurial handle this? We haven't tried to do anything like this and I can't really wrap my head around how it would be done.

Pat
  • 16,515
  • 15
  • 95
  • 114
oob
  • 1,948
  • 3
  • 26
  • 48
  • http://stackoverflow.com/questions/854930/mercurial-cherry-picking-changes-for-commit – zerkms Apr 23 '12 at 21:22
  • 1
    I find it easiest if the "main development branch" is itself a tree, where different changes are in their own ("anonymous") branches that grow off and then get put back in... –  Apr 23 '12 at 21:34
  • 3
    (not an answer, hence the comment) *"I think it would have been better to make the change on the older branch"*... It *may* have been even better to apply that bugfix as a "daggy fix": you rollback to where the bug was introduced, you commit your fix and you merge upstream. Applying it "as early as possible" *may* even be better that applying first to your "older branch" (whatever that is). For small bugfixes daggy fix do totally rock (IMHO): http://mercurial.selenic.com/wiki/DaggyFixes – TacticalCoder Apr 24 '12 at 01:22
  • @TacticalCode - maybe it wasn't an answer, but i will try that in the future. – oob Apr 25 '12 at 03:00

1 Answers1

14

Yes, you have two good options:

Graft: new in Mercurial 2.0

This version introduced the graft command which can backport changes in an intelligent way. The "intelligence" is that it will use merges internally and this means that you get

  • Support for renames: Imagine that you fixed the bug in file foo.c on the development branch. In the older maintenance branch foo.c was called bar.c. Using hg graft, the change to foo.c can be correctly merged into the old bar.c.

  • Three-way merges: Grafting involves twisting the graph around and merging in that temporary graph. The advantage of three-way merges is that you can use your normal graphical merge tool to resolve conflicts.

To copy the tip of default onto old-branch you simply run

$ hg update old-branch
$ hg graft default

Transplant: older versions

Before we had the graft command, the transplant extension was the way to go. This simple extension will export a changeset as a patch and try to apply the patch onto some other revision.

Because we're dealing with "dumb" patches things like renames will not be taken into account and you will not get support for your merge tool since there is no three-way merge. Despite of this, I've found that transplant works really well in practice.

Using transplant is simple:

$ hg update old-branch
$ hg transplant default

This is very close to running

$ hg update old-branch
$ hg export default | hg import -

except that transplant also adds a piece of meta data that records the original changeset in the transplanted changeset. This can be used to skip future transplants.

Community
  • 1
  • 1
Martin Geisler
  • 72,968
  • 25
  • 171
  • 229