DEV Community

Cover image for Watch Out for Cherry-Pick
Nowshin Alam Owishi
Nowshin Alam Owishi

Posted on

Watch Out for Cherry-Pick

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>
Enter fullscreen mode Exit fullscreen mode

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?

  1. When you are working and testing on your branch and want to reuse one commit in other branches without merging everything.
  2. In case of emergency fixes. Like, introducing a hotfix to a previous release.
  3. You need a specific functionality from a branch that is not fully ready to merge yet.
  4. 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:

Situation 1 before merge

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 1 with merge conflict

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

  1. Create a temporary fix in a new commit that disables notifications: NOTIFICATIONS_ENABLED = false in your bugfix/login branch.
  2. Cherry-pick that commit into the production branch as an emergency patch.
  3. In your bugfix/login branch, you fix the root issue. After thorough testing, you re-enable notifications (NOTIFICATIONS_ENABLED = true) and merge your bugfix/login branch to production 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.

Situation 2

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.

Situation 3

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, or git 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>
Enter fullscreen mode Exit fullscreen mode

    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>)
Enter fullscreen mode Exit fullscreen mode

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)