It’s a bit of a read, but spending a few minutes now could save you hours of pain later.
What is cherry-pick 🍒?
In many situations, you might want to copy specific code changes from one branch into another. Git offers a command for this:
git cherry-pick <commit-hash>
This command copies the content of a specific commit (by hash) and applies it to your current branch.
Keep in mind: Git applies only the changes from the commit, not the commit itself.
- Applies the commit's diff as a new disconnected change
- Creates duplicate commits with a different SHA hash
- Maintains no relationship to the original commit
When to use it?
- When you are working and testing on your branch and want to reuse one commit in other branches without merging everything.
- In case of emergency fixes. Like, introducing a hotfix to a previous release.
- You need a specific functionality from a branch that is not fully ready to merge yet.
- Need to revive specific commits from a branch that won't be merged anymore.
Cherry-pick is a powerful tool, but it’s not a one-size-fits-all fix. While it can be convenient, it must be used with caution. This doesn’t mean cherry-picking is inherently bad or should be avoided completely, but it does carry risks. Often, issues arise not from the tool itself, but from how it’s used. These mistakes are common, which is why understanding them is crucial. I will address some of the potential risks of cherry-picking and how to dodge them.
The Hidden Dangers of Git Cherry-Picking
Situation 1: Merge Hell
Imagine you're working on the feature/dashboard
branch. Halfway through, you discover a critical API bug that needs to be fixed for your upcoming feature. On the other hand, your teammate, Ahmed, is already fixing it in his bugfix/api
branch with other issues, but he needs a couple of days to complete all the fixes.
What You Do
- Ahmed provides the fix you need with a commit. Later, he tells you to cherry-pick that commit. So, let's say the hash is F and you cherry-pick using the specific commit hash:
git cherry-pick F
- The fix works! You continue developing your dashboard. Currently, the situation is like the image below:
A week later, Ahmed merges his entire bugfix/api
branch to main
. Remember, it also has the commit that you cherry-picked earlier.
The Surprise
Later, you find conflicts of identical changes while trying to merge your dashboard. Depending on the changes of the commits, it can be complex.
What Git sees
- The original fix (from Ahmed's merge)
- Your cherry-picked version (same changes, different commit hash)
- Treats them as conflicting changes Now it hurts because you're forced to manually resolve conflicts that shouldn't exist, wasting hours on what should have been a clean merge. The situation can be described as in the image below.
Situation 2: Disappearing Changes
Now, imagine you're fixing a security issue with login notifications, in your bugfix/login
branch. You need to disable the feature temporarily while you fix the underlying problem.
Your Steps
- Create a temporary fix in a new commit that disables notifications:
NOTIFICATIONS_ENABLED = false
in yourbugfix/login
branch. - Cherry-pick that commit into the production branch as an emergency patch.
- In your
bugfix/login
branch, you fix the root issue. After thorough testing, you re-enable notifications (NOTIFICATIONS_ENABLED = true
) and merge yourbugfix/login
branch toproduction
branch. Everything seems fine, no conflicts.
The Silent Disaster
Users report notifications are still off, and you don't know why. I have added an image so that you can get the situation. I've shown the value of NOTIFICATIONS_ENABLED
at the top of each commit bubble.
What Happened?
Git will compare by the 3-way comparison of Git merge:
- The value that the base commit has, which is true. Since the cherry-picked branch has a changed hash, it won't be considered the common base commit.
- The latest value of the bugfix/login branch is true, so Git thinks there were no changes.
- The latest value of the production branch is false, so Git thinks there was a change made later, and without showing any conflict, it replaces the value with false.
Situation 3: The Extra Changes
Suppose your feature.js
on main
branch has a method named isFeatureEnabled()
, that is modified in bugfix/user-access
branch, and now you wanna cherry-pick the latest changes made to that method onto the main
branch. Let's say the commit is C
. After running git cherry-pick C
, you are seeing extra changes that were not in the commit you have picked.
I have shown the changes of feature.js
across commits and branches.
The Hidden Problem
When you cherry-pick a commit, Git calculates the diff between that commit and its parent, and tries to apply that diff onto your current HEAD. This diff includes not only the changed lines, but also context lines (unchanged lines around the change). Git uses context to figure out where in your codebase the patch should be applied. If the context doesn't match because your branch has diverged significantly, Git can't put the patch cleanly and will throw a conflict, prompting you to resolve it manually. That’s why you might see lines from earlier commits (B
) appear again during a cherry-pick of commit C
, especially when commit C
was built on top of changes you don't have in your branch.
How to Fix?
Situation 1: Merge Hell
Abort the merge, rebase
your source branch onto the target branch. Test your changes thoroughly and review the diffs to ensure everything looks right. It might take extra time, but it's better than dealing with a broken merge later.
Situation 2: Disappearing Changes
This one’s tricky since Git won’t show conflicts. If you've already merged and pushed, you'll need to either drop the bad commit or manually fix the logic. Then again, rebase
your source branch onto the target branch and carefully review git diff
before merging.
Situation 3: The Extra Changes
Be careful while fixing conflicts. Be aware of your changes, and perform a thorough review.
So, rebase
or/and git diff
with thorough review is my ultimate solution.
How to Avoid These Situations?
- Always review the difference after cherry-picking, then push to the remote, even if Git shows no conflicts at all. Do
git diff HEAD^ HEAD
, orgit show
. This ensures the commit didn’t smuggle in unrelated changes due to contextual patching. - Avoid cherry-picking someone else's commit unless necessary. If needed, create a patch branch and merge it into other branches. This preserves the original commit hash and avoids duplication. If cherry-picking is unavoidable, communicate clearly with your team and track which commits were moved.
- Use
-x
to track cherry-picked commits.
git cherry-pick -x <commit-hash>
This appends the source commit hash to the message. You can see the commit message using git log -1
:
commit aa334sss (HEAD -> temp-commit)
Author: iamauthor <author@gmail.com>
Date: Wed Aug 6 16:47:06 2025 +0600
test: try cherry
(cherry picked from <commit-hash>)
Isn't There a Better Way to Solve?
There are plenty of ways to fix cherry-pick issues, but I stick to what I’m comfortable with. cherry-pick
is just a tool, and like any tool, it can make life easier if used properly. Git doesn’t know how your code works, so while it automates a lot, it still needs your attention. That’s why I am mentioning thorough reviews. And sure, technical tools help, but nothing beats solid team communication and regularly syncing with the branches you’re merging into. Take the time to understand Git and use it carefully, instead of picking up a bunch of complex tricks only to forget them later.
See you next with Danger: You lost work or rewrote authorship after squash and force-push!
Top comments (0)