The way a cherry-pick works is by taking the diff a changeset represents (the difference between the working tree at that point and the working tree of its parent), and applying it to your current branch.
So, if a commit has two or more parents, it also represents two or more diffs - which one should be applied?
You're trying to cherry pick fd9f578, which was a merge with two parents. So you need to tell the cherry-pick command which one against which the diff should be calculated, by using the -m option. For example, git cherry-pick -m 1 fd9f578 to use parent 1 as the base.
Parent 1 is the "first parent", 2 is the "second parent", and so on. The order is the one in which they're listed in the commit (as viewed by git show and the like).
I can't say for sure for your particular situation, but using git merge instead of git cherry-pick is generally advisable. When you cherry-pick a merge commit, it collapses all the changes made in the parent you didn't specify to -m into that one commit. You lose all their history, and glom together all their diffs. Your call.
The way a cherry-pick works is by taking the diff a changeset represents (the difference between the working tree at that point and the working tree of its parent), and applying it to your current branch.
So, if a commit has two or more parents, it also represents two or more diffs - which one should be applied?
You're trying to cherry pick fd9f578, which was a merge with two parents. So you need to tell the cherry-pick command which one against which the diff should be calculated, by using the -m option. For example, git cherry-pick -m 1 fd9f578 to use parent 1 as the base.
Parent 1 is the "first parent", 2 is the "second parent", and so on. The order is the one in which they're listed in the commit (as viewed by git show and the like).
I can't say for sure for your particular situation, but using git merge instead of git cherry-pick is generally advisable. When you cherry-pick a merge commit, it collapses all the changes made in the parent you didn't specify to -m into that one commit. You lose all their history, and glom together all their diffs. Your call.
-m means the parent number.
From the git doc:
Usually you cannot cherry-pick a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows cherry-pick to replay the change relative to the specified parent.
For example, if your commit tree is like below:
- A - D - E - F - master
\ /
B - C branch one
then git cherry-pick E will produce the issue you faced.
git cherry-pick E -m 1 means using D-E, while git cherry-pick E -m 2 means using B-C-E.
Can you cherry-pick pull requests??
Gerrit workflow: Cherry-picking vs merging?
git - What are the pros and cons of using cherry-pick versus merge for release management? - Software Engineering Stack Exchange
git - How to cherry-pick merge commits? - Stack Overflow
Using git for quite some time but never ran into an issue where I want to cherry-pick a pull request. I know you can cherry-pick individual commits, but the PR contains around 50 commits, so is there a short way to do it??
Just wondering because of the workflow we have in our industry projects:
-
All commits go through a code review process via Gerrit.
-
The
masterbranch is kept strictly linear. When there is a feature branch, it ultimately eventually gets squashed into or rebased onto themasterbranch. -
At some point, a
releasebranch is split off from the master branch. After that, most commits are usually still cherry-picked betweenreleaseandmaster. Generally, all commits of thereleasebranch are also on themasterbranch, but risky changes are only onmaster.
So the history looks something like
··· -- A -- B -- C -- D -- R1 -- E -- F -- G -- R2 -- H (master)
`-- B'-- C'-- D'-------- E'-- F'-- G'-------- H'(release)
This made me wonder, if it would be more accurate to commit to release and merge to master. Which, to be fair, looks a lot messier:
··· -- A -- B -- C -- D -- R1 -- E -- F -- G -- R2 -- H (master)
\ / / / / / / /
B' -- C'-- D'-------- E'-- F'-- G'-------- H' (release)
I can see the advantage of keeping the master history a straight line, but are there also issues with that approach by losing the actual relationship between the commits?
Note that the code review interface of Gerrit clearly favors the cherry-pick approach, even though this can result in non-conflicting commits having different order between master and release branch (which I guess doesn't really matter for anything).
Merging provides a clearer and more complete picture of the changes leading up to each feature release or bug fix, making it easier for developers to trace back and understand why certain decisions were made. Cherry-picking can create fragmented or isolated commits, which makes tracking the development history and debugging more complex. It also increases the risk of human error, such as accidentally omitting commits, including those that other changes depend on. In practical terms, if you cherry-pick only some commits from a sequence with dependencies, you might end up with code that fails to compile, causes bugs, or doesn’t reflect the intended feature because the cherry-picked commits lack the full context. Merging, on the other hand, preserves the order and structure of dependent commits, reducing these risks.
If you are not using CI at the moment, and if you decide to go that way in future, merging is more CI-friendly. In my experience, CI tools (Jenkins springs to mind) handle branch merges much better than workflows that rely on individual cherry-picked commits, which are applied one-by-one to the target branch. Proper merging creates more stable integration points and enables smoother automation, both of which support reliable testing and deployment.
Merging is widely adopted as a best practice because it preserves commit history and dependencies, supporting a stable and predictable workflow. This also simplifies onboarding, as new team members are likely familiar with standard git workflows.
Finally, depending on how your company handles releases, merging provides the QA team with a consistent and complete set of changes. This makes test planning and execution more straightforward, reducing the risk of missing dependencies or introducing regressions. Unlike cherry-picking, merging allows QA to validate cohesive features or fixes in one go, minimising repeated testing and simplifying communication around what is included in each build. Additionally, merging enhances CI integration, making automated tests more reliable and reducing manual checks, so QA can focus on thorough testing rather than troubleshooting incomplete changes.
Some details about the git flow the team uses could help getting answers closer to what you are looking for than How do I explain ${something} to ${someone}? that has been mentioned in comments.
From description it seems there are several branches constantly out of sync, the team is uncertain about what branch the code in production has been released. dev branch is behind the release branch while it should be the other way around, the dev branch it should be ahead of production code and that's why the team finds git cherry-pick more convenient than merge. Is the dev a development slow down? 'cause this is what it seems to happen. I would say a redesign of the git flow the team follows would shed a different light over the git commands the team members use.
Lets assume you have something like this:
X - master
|
|
M
|\
| \
X B - merged_feature_branch
| |
| |
X A X - cherry_pick_destination
| / |
|/ |
X X
| /
| /
Now you have two choices:
- cherry pick only
AandB - cherry pick
Magainst first parent (-m 1)
Both solution will introduce same change, but IMHO first approach is more readable.
In case if some conflicts where resolved when committing M then second option may be preferred..
If you have to cherry-pick a range of commits without the merge commits, rather than doing
git cherry-pick A..B
You can put the range into a subcommand where you suppress merge commits :
git cherry-pick $(git rev-list --reverse --no-merges A..B)