Fix: git cherry-pick error: could not apply commit (conflict)
Part of: Docker, DevOps & Infrastructure
Quick Answer
How to fix git cherry-pick conflict errors caused by diverged branches, overlapping changes, missing context, renamed files, and merge commits.
The Error
You run git cherry-pick and get:
error: could not apply abc1234... Fix login bug
hint: After resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' and run 'git cherry-pick --continue'.
hint: To skip this patch, run 'git cherry-pick --skip'.
hint: To abort and go back to the previous state, run 'git cherry-pick --abort'.Or variations:
CONFLICT (content): Merge conflict in src/auth/login.js
error: could not apply abc1234... Fix login bugerror: cherry-pick is not possible because you have unmerged files.error: your local changes would be overwritten by cherry-pick.fatal: bad object abc1234 — not a valid commitGit tried to apply a commit from one branch to your current branch, but the changes conflict with your existing code. The file context has diverged enough that Git cannot automatically merge the changes.
Why This Happens
git cherry-pick takes a commit from one branch and replays it on your current branch. It applies the diff of that commit to your working tree. If the code around the changed lines is different on your branch, Git cannot determine how to apply the patch and reports a conflict.
Common causes:
- Diverged code. The file has been modified differently on both branches since the original commit.
- Overlapping changes. Both branches modified the same lines.
- Missing dependencies. The cherry-picked commit depends on earlier commits that are not on your branch.
- File was renamed or moved. The file path changed on one of the branches.
- Different formatting. Whitespace changes, code reformatting, or line ending differences.
- Cherry-picking a merge commit. Merge commits require special handling.
The reason cherry-pick is more fragile than merge is that it has less context. A merge knows about the common ancestor of the two branches and can use that to reason about three-way diffs. Cherry-pick only has the diff of one commit and the current state of your branch — no shared ancestor to anchor the patch. When the surrounding code drifts even slightly (a renamed variable, a moved import block, a reformatted line), Git cannot find the right insertion point and reports a conflict.
The mental model that helps: think of cherry-pick as git apply with author metadata, not as a small merge. The patch either applies cleanly to the current file contents or it does not. Most “cherry-pick is hard” experiences come from cherry-picking commits that are too old, too far across the divergence, or that depend on changes that never made it to the target branch.
In Production: Incident Lens
Cherry-pick conflicts in production are almost always a hotfix scenario: a fix landed on the main development branch, the release branch is two weeks behind, and someone needs to ship that one fix without dragging in the other 50 commits. The conflict is the price of branch divergence — and the way you resolve it determines whether the fix actually fixes the production problem or quietly drops half of itself.
- How it surfaces: Not as a 5xx spike — this one shows up in your terminal during the incident response, not on a dashboard. The pattern is: incident declared, fix identified, fix commit found,
git cherry-pick <sha>onto the release branch, conflict appears. The pressure is on; the temptation to resolve quickly is high; the risk of dropping part of the fix is highest exactly when it matters most. - Blast radius: Zero if you catch the conflict before pushing. Catastrophic if you resolve it wrong and the hotfix appears to be in the release but the actual behavior change is missing — the production incident continues, you assume the fix is deployed, you waste an hour investigating the wrong thing. The worst variant is a partial conflict resolution that compiles but does not fix the bug.
- What catches it:
git statusafter the cherry-pick is the obvious signal, but the meaningful one is the verification step after the deploy. A smoke test or canary that exercises the exact bug being fixed will tell you if the cherry-pick actually applied the fix. Without that test, the conflict resolution is unverified. - Recovery sequence: Three-step decision tree. (1) If the conflict touches more than the lines the fix intended to change, abort with
git cherry-pick --abortand reconsider — the divergence is too large for a clean cherry-pick. (2) If the conflict is on adjacent context only, resolve manually with both versions visible, then run the test that exercises the fixed bug. (3) If you cannot find a safe resolution under time pressure, ship a forward-only fix written against the release branch directly. Do not blindly use-X theirsto “make it apply” — that strategy drops your local changes silently. - Postmortem preventive: Two durable controls. First, enable
git rerere(git config rerere.enabled true) so resolutions to recurring conflicts are remembered and replayed. This is essential for teams that cherry-pick between long-lived branches regularly. Second, automate the “did the cherry-pick actually land?” check: a CI job on the release branch that runs the regression test for every recent fix taggedhotfix. The check fails if the regression returns, regardless of whether the commit appears in the log.
Fix 1: Resolve the Conflict Manually
The standard approach. Open the conflicted files and resolve:
# See which files have conflicts
git status
# Both modified: src/auth/login.jsOpen the file and find conflict markers:
<<<<<<< HEAD
// Your current branch's version
function login(email, password) {
return authService.signIn(email, password);
}
=======
// The cherry-picked commit's version
function login(email, password) {
const result = authService.signIn(email, password);
logLoginAttempt(email);
return result;
}
>>>>>>> abc1234 (Fix login bug)Resolve by keeping the correct version:
// Combine both changes (usually what you want)
function login(email, password) {
const result = authService.signIn(email, password);
logLoginAttempt(email);
return result;
}Complete the cherry-pick:
git add src/auth/login.js
git cherry-pick --continueGit opens your editor for the commit message. Save and close to complete the cherry-pick.
Pro Tip: Use a merge tool for complex conflicts. Run
git mergetoolto open your configured tool (VS Code, IntelliJ, Beyond Compare). Visual diff tools make it much easier to understand what both sides changed.
Fix 2: Abort and Try a Different Approach
If the conflicts are too complex, abort and rethink:
git cherry-pick --abortThis restores your branch to the state before the cherry-pick attempt.
Alternatives to cherry-pick:
# Merge the entire branch instead
git merge feature-branch
# Rebase (if you want a linear history)
git rebase feature-branch
# Create a patch and apply manually
git format-patch -1 abc1234
git apply --3way 0001-Fix-login-bug.patchPick specific files instead of the whole commit:
# Get just one file from another branch
git checkout feature-branch -- src/auth/login.js
# Or show the diff and apply selectively
git diff abc1234^..abc1234 -- src/auth/login.js | git applyFix 3: Cherry-Pick Multiple Related Commits
If the commit depends on earlier commits, cherry-pick them in order:
# Cherry-pick a range of commits (oldest to newest)
git cherry-pick abc1234^..def5678
# Or cherry-pick multiple specific commits
git cherry-pick abc1234 bcd2345 cde3456Find which commits the target depends on:
# See what files the commit changed
git show --stat abc1234
# See the full diff
git show abc1234
# Find commits that modified the same files
git log --oneline -- src/auth/login.jsIf commits must be applied in order:
# List commits on the source branch since it diverged
git log --oneline main..feature-branch
# Cherry-pick from oldest to newest
git cherry-pick commit1 commit2 commit3Common Mistake: Cherry-picking a commit that depends on changes from previous commits. If commit C modifies a function that was added by commit B, cherry-picking only C will fail. You need both B and C, in order.
Fix 4: Fix Cherry-Picking Merge Commits
Merge commits have two parents. Git does not know which parent to diff against:
git cherry-pick abc1234
# error: commit abc1234 is a merge but no -m option was given.Fix — specify the parent:
# -m 1 uses the first parent (usually the branch being merged into)
git cherry-pick -m 1 abc1234
# -m 2 uses the second parent (the branch being merged)
git cherry-pick -m 1 abc1234Usually -m 1 is what you want. The first parent is the mainline branch, and the diff represents the changes introduced by the merge.
Better approach — cherry-pick the individual commits instead:
# Find the actual commits in the merged branch
git log --oneline abc1234^2..abc1234
# abc1234 Merge branch 'feature'
# bcd2345 Fix login bug
# cde3456 Add login logging
# Cherry-pick the individual commits
git cherry-pick cde3456 bcd2345Fix 5: Fix Unmerged Files Error
If you have unresolved conflicts from a previous operation:
error: cherry-pick is not possible because you have unmerged files.Resolve the existing conflicts first:
# See what's unresolved
git status
# Resolve conflicts in each file, then:
git add <resolved-files>
# If you were in the middle of a previous cherry-pick
git cherry-pick --continue
# Or abort everything and start fresh
git cherry-pick --abortFix 6: Fix Local Changes Error
If you have uncommitted changes:
error: your local changes would be overwritten by cherry-pick.Fix — stash your changes:
git stash
git cherry-pick abc1234
git stash popFix — commit your changes first:
git add .
git commit -m "WIP: save current work"
git cherry-pick abc1234Fix 7: Use —strategy-option for Conflict Resolution
Automated conflict resolution strategies:
# Prefer the cherry-picked commit's version when there's a conflict
git cherry-pick -X theirs abc1234
# Prefer your current branch's version
git cherry-pick -X ours abc1234
# Ignore whitespace changes
git cherry-pick -X ignore-all-space abc1234-X theirs automatically resolves conflicts by taking the cherry-picked commit’s version. Useful when you know the incoming changes should win.
-X ours keeps your current branch’s version. Useful when you only want non-conflicting parts of the cherry-picked commit.
Warning: These options only affect conflicting hunks. Non-conflicting changes from both sides are always included.
Fix 8: Cherry-Pick Without Committing
Apply the changes without creating a commit, so you can review and modify:
git cherry-pick --no-commit abc1234
# or
git cherry-pick -n abc1234
# Changes are staged but not committed
git status
git diff --cached
# Modify if needed
git checkout -- src/unwanted-file.js # Undo specific files
# Commit when ready
git commit -m "Cherry-pick login fix from feature branch"This gives you full control over what gets committed and the commit message.
Still Not Working?
Check that the commit exists in your repo:
git cat-file -t abc1234
# Should output: commit
# If "fatal: bad object", the commit is not in your local repo
# Fetch from remote first
git fetch origin
git cherry-pick abc1234Check for binary file conflicts. Binary files cannot be auto-merged:
# Accept the cherry-picked version
git checkout --theirs path/to/binary.png
git add path/to/binary.png
git cherry-pick --continueCheck for submodule conflicts. Submodule pointer changes can conflict and need manual resolution.
Check for line-ending and EOL conflicts. If the source branch was authored on Windows (CRLF) and the target branch on Linux (LF), every line of the diff can register as a conflict even when the actual content is identical. Run git config core.autocrlf input and re-normalize line endings with git add --renormalize . before attempting the cherry-pick.
Check for .gitattributes filter conflicts. Smudge/clean filters or LFS pointers can transform file contents between checkout and commit. A cherry-pick that touches an LFS-tracked binary may conflict on pointer files even when the underlying objects are unchanged. Run git lfs status to see what LFS thinks is in flight.
Verify the cherry-pick landed in the deploy. After resolving and pushing, confirm the commit is in the deployed artifact: git log --oneline release-branch | grep <sha>. Then verify behavior with a smoke test that targets the specific bug. A conflict resolution that compiles is not the same as a fix that works.
Check for git rerere replaying a stale resolution. If rerere is enabled, Git silently replays a remembered resolution. If that resolution was wrong on a previous occasion, it is silently wrong now too. Inspect with git rerere status and clear with git rerere clear if the replayed resolution looks suspicious.
For general merge conflicts, see Fix: Git merge conflict. For rebase conflicts, see Fix: Git rebase conflict. For stash conflicts, see Fix: Git stash pop conflict. If your push is rejected after pushing the cherry-pick, see Fix: Git push rejected non-fast-forward.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: DVC Not Working — Remote Push Errors, Pipeline DAG Issues, and Git Integration
How to fix DVC errors — dvc push authentication failed, dvc pull file missing, pipeline stage not reproducing, cache out of disk space, dvc add vs dvc stage, conflict with git LFS, and S3/GCS remote setup.
Fix: Git Hooks Not Running — Husky Not Working, pre-commit Skipped, or lint-staged Failing
How to fix Git hooks not executing — Husky v9 setup, hook file permissions, lint-staged configuration, pre-commit Python tool, lefthook, and bypassing hooks in CI.
Fix: Git Keeps Asking for Username and Password
How to fix Git repeatedly prompting for credentials — credential helper not configured, HTTPS vs SSH, expired tokens, macOS keychain issues, and setting up a Personal Access Token.
Fix: Undo git reset --hard and Recover Lost Commits
How to undo git reset --hard and recover lost commits using git reflog — step-by-step recovery for accidentally reset branches, lost work, and dropped stashes.