Easiest way to "cherry-pick a merge"
Asked Answered
C

2

6

I know the title is a little woolly - hence the quotes!

Say I have a branch, b_feature that was branched from and merged into the main development branch b_master. There exists another branch, b_release, that I wish to add these changes to (as a point release). b_master and b_release have been diverged and will never be merged again.

---------Bm----k1-----Mm-----> b_master (k1 isn't to be included in b_release)
 \        \          /
  \        c1--c2--c3  (b_feature)
   \
    \----Br---------Mr-----> b_release
          \        / 
           cA-cB-cC

I know I can cherry-pick the whole thing as a single diff with git cherry-pick -m Mm, giving

     ----Br--Squashed----> b_release

where Squashed is a commit containing all the changes of the feature, with the message of the merge Mm.

But what if I want to retain the change history and the individual commit messages? I can always manually cherry-pick with this approximate workflow:

git checkout b_release
git checkout -b b_release_feature
git cherry-pick c1^..c3
git checkout b_release
git merge b_release_feature
git commit --amend --reedit-message=Mm
git branch -d b_release_feature

But this seems like a clunky workaround to a more elegant solution that I don't know!

rebase --onto b_release Bm Mm also doesn't seem to produce the result I am looking for.

Any better way to do it?

Cherlynchernow answered 27/1, 2016 at 11:47 Comment(0)
I
1

I think rebase is a more proper tool than cherry-pick here, although the difference is minor. Here is how I would have done it. First attach the b_release_feature branch to the source branch and then rebase it onto the target branch.

git checkout -b b_release_feature c3
git rebase --onto b_release c1^ b_release_feature
git checkout b_release
git merge b_release_feature
git commit --amend --reedit-message=Mm
git branch -d b_release_feature
Ironware answered 31/1, 2016 at 1:31 Comment(0)
L
0

But what if I want to retain the change history and the individual commit messages?

Then I see no reason not to create a true merge into b_release.

git checkout b_release
git merge ":/c3"

Giving you

---------Bm----k1-----Mm-----> b_master (k1 isn't to be included in b_release)
 \        \
  \        c1--c2--c3 \
   \                   \
    \----Br---------Mr--Mc3---> b_release
          \        /
           cA-cB-cC

And then (don’t know why you want this message)

message=$(git log -1 --format=%B ":/Merge branch 'b_feature'")
git commit --amend --message="$message"

Having multiple commits with both the same message and the same changes (diffs) in the history is confusing. Sometimes it is necessary because you have to do a cherry-pick, but this doesn’t look like such a case to me.

Setup

git init
git commit --allow-empty -mInit
git commit --allow-empty -m'After init'
git commit --allow-empty -mBm
git commit --allow-empty -mk1
git checkout -b
git checkout @~
git checkout -b b_feature
git commit --allow-empty -mc1
git commit --allow-empty -mc2
git commit --allow-empty -mc3
git checkout main
git merge --no-ff b_feature
git checkout ':/After init'
git checkout -b b_release
git commit --allow-empty -mBr
git checkout -b other
git commit --allow-empty -mCa
git commit --allow-empty -mCb
git commit --allow-empty -mCc
git checkout -
git merge --no-ff other
git checkout main
Lail answered 6/5, 2023 at 10:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.