5

I am trying to merge part of a commit from the default branch (not all files and parts of other files) to a named branch. I tried graft, but it just takes the whole commit wthout giving me a chance to choose. How would this be done?

Example:

A---B---C---D
      \
       -E---(G)

G does not exist yet. Lets say C and D each added 5 files and modified 5 files. I want G to have 2 of the 5 files added at C, all the modifications to one of the files and one modification to another file. I would ideally like it to also have something similar from D.

When I selected graft to local..., all I got was the whole C change-set. Same for merge with local...

user2864740
  • 60,010
  • 15
  • 145
  • 220
Baruch
  • 20,590
  • 28
  • 126
  • 201
  • 2
    Mercurial itself, as far as I know, doesn't support this kind of selective merge. What you *can* do is perform a normal merge, then revert the files that you don't want merged, and make manual changes to the files that you want to merge partially. Finally, commit the merge. – voithos Jun 11 '13 at 21:32
  • @voithos Is that the standard way of getting a bug-fix from one branch to another? I would think this would be a common and supported scenario, no? – Baruch Jun 11 '13 at 22:08
  • 2
    It's not standard, it's not even recommended. Of course, best practice dictates that a bug fix should be **its own changeset**, so you shouldn't have to pick and choose individual files. If it were, you could use graft (or just merge, if bug fixes is all you have in the default branch). – voithos Jun 11 '13 at 22:22
  • Does this answer your question? [Mercurial: Merging one file between branches in one repo](https://stackoverflow.com/questions/1078881/mercurial-merging-one-file-between-branches-in-one-repo) – StayOnTarget Apr 27 '20 at 14:26

1 Answers1

6

The unit of merging is a whole changeset, so C and D should have been committed in smaller pieces. You could now merge the whole thing and revert some files, but this will have the result that you won't be able to merge the rest later-- they're considered merged already.

What I'd do is make a branch parallel to C-D, rooted at B in your example, that contains copies of the changes in C and D but splits them into coherent parts. Then you can merge whole changesets from that, and close (or or perhaps even delete) the original C-D branch.

      C---D
     / 
A---B--C1--D1--C2--D2    (equivalent to C--D)
     \   
      E---(G?)

In the above, C1 and C2 together are equivalent to C. While I was at it I went ahead and reordered the four new changesets (use a history-rewriting tool such as rebase), so that you can then simply merge D1 with E:

      C---D
     / 
A---B--C1--D1--C2--D2
     \      \
      E------G

If reordering the new changesets is not an option, you'd have to do some fancy tapdancing to commit the partial changesets in the order C1, D1, C2, D2; it's probably a lot less trouble to use graft (or transplant) to copy the changes that you're not allowed to merge separately. E.g., in the following you can still merge C1, but then you need a copy of D1 (labeled D1') since there's no way to merge it without pulling C2 along with it.

      C---D
     / 
A---B--C1--C2--D1--D2
     \  \
      E--G1--D1'
alexis
  • 48,685
  • 16
  • 101
  • 161