35

I know Rebase is a (bundled) extension, while Graft is a core feature (that replaced the Transplant (bundled) extension).

graft is documented as:

copy changes from other branches onto the current branch

This command uses Mercurial's merge logic to copy individual changes from other branches without merging branches in the history graph. This is sometimes known as 'backporting' or 'cherry-picking'.

rebase is documented as:

Rebase allows moving commits around in Mercurial's history (using a series of internal merges). This has many uses:

  • moving changesets between branches
  • "linearizing" history
  • reordering changesets
  • collapsing multiple changes into one changeset

Both seem to use merging to move or copy changesets between branches.

Graft copies. Rebase moves. But rebase --keep copies.

So often it seems I can accomplish my goal of copying a changeset either way. Does it matter which one I use? When should I prefer one over the other?

E.g. should graft only be used when copying to a different named branch? Or only when there's just a single changeset?


Edit: Could it be that rebase is a potentially unsafe superset of graft, but can only be used with draft changesets during development for editing local history, while graft is a safe subset of rebase that can be used with public changesets during maintenance for backporting?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Peter
  • 3,322
  • 3
  • 27
  • 41
  • 2
    Note that my main question is not necessarily to get a list of all the minor technical differences, but to find a rule / rationale to decide between them **when either seem to work**. Or should I just use whichever seems more convenient? – Peter Apr 09 '15 at 14:04

1 Answers1

42

hg graft allows "cherry-picking," as you noted in your question. For example, you can run hg graft -D "2085::2093 and not 2091" to copy only some changes from another revision. By comparison, hg rebase (with or without --keep) will grab whatever changeset you specify and all of its decendant changes.

Also, rebase allows you to collapse changesets (with --collapse). As far as I can tell, graft does not.

One more difference I have noticed: hg graft --edit 123 lets you graft revision 123 to the working directory and edit the commit message. I can't find an hg rebase equivalent. I should point out, though, that hg histedit also allows for editing the commit message while rebasing.

There are probably other differences that I am not thinking of. SO community: feel free to point those out in the comments, and I will happily revise this answer to make it more complete.

See the graft documentation and the Rebase Extension documentation for more details.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
elixenide
  • 44,308
  • 16
  • 74
  • 100
  • Doesn't `hg rebase --rev "2085::2093 and not 2091"` also allow "cherrypicking"? – Peter Apr 09 '15 at 13:56
  • 4
    Graft will copy _and_ refer back to the original changeset, which is very useful in cherry-picking. You should be able to see this using 'hg log --debug'. – Mathiasdm Apr 09 '15 at 14:02
  • 2
    @Mathiasdm: Do you mean the `graft_source`? Doesn't rebase have the same thing with `rebase_source`? – Peter Apr 09 '15 at 14:07
  • 3
    Oh, that's interesting, I didn't know rebase_source existed :-) Hm, in that case, I don't think there's much difference between the rebase you suggest versus graft. – Mathiasdm Apr 09 '15 at 14:10
  • 1
    @Peter Maybe. I can't find anything in the docs about doing that kind of selective rebasing. I just tested it with a sample repository and it seemed to turn out alright, although I got a couple of unfamiliar complaints from hg along the way. Note, though, that it definitely only works with `hg rebase --keep` -- you can't do a selective rebase without `--keep`, or hg will flip out. – elixenide Apr 09 '15 at 14:14
  • 2
    `hg rebase` doesn't allow to "cherry-pick" changesets that are an ancestor of the destination, even with `--keep`, but `hg graft` does with `--force`. This may be useful e.g. when a changeset has been applied earlier and later been reverted, and you want to apply it again now. – Simon Aug 06 '19 at 07:12