Git Cherry-Pick Duplicate Conflict — Missing Source SHA
Cherry-pick creates a new SHA, causing duplicate merge conflicts during later merges.
- git stash push -u -m 'label': saves tracked + untracked changes with a description
- git stash pop: restores and removes from stack — deletes stash even on conflict
- git stash apply: restores but keeps in stack — safer when conflicts are possible
- git cherry-pick
: replays a commit's diff onto current branch with a new SHA - git cherry-pick -n
: applies changes without committing — combine multiple into one
Imagine you're a chef mid-way through making a complex sauce when your manager rushes in and says 'drop everything — the dessert is on fire.' Git stash is like wrapping your half-chopped ingredients in cling film and putting them in the fridge so nothing is wasted. Cherry-pick is like looking at another chef's finished dish, spotting one brilliant garnish they added, and copying just that garnish onto your own plate — without taking their whole meal.
Two commands solve the two most common context-switching problems in Git: stash and cherry-pick. Stash shelves uncommitted changes so you can switch branches cleanly. Cherry-pick copies specific commits from one branch to another without merging the entire branch.
Stash is a local-only stack — not a branch, not a commit in your history, not synced to the remote. It is ideal for short context switches but dangerous for anything you want to share or keep long-term. Cherry-pick creates a new commit with a new SHA on the target branch. The original commit is untouched. This matters because Git may not recognise the two as the same change during a future merge, causing duplicate conflicts.
Common misconceptions: that stash saves everything (it excludes untracked files by default), that cherry-pick moves commits (it copies them), and that stash pop is always safe (it deletes the stash even on merge conflicts).
Git Stash — Parking Your Work Without a Throwaway Commit
When you run git stash, Git takes everything in your working directory and staging area that differs from HEAD, bundles it into a special stash entry, and hands you back a perfectly clean working tree. The stash lives on a per-repo stack — last in, first out — and it persists across branch switches, which is the whole point.
The key mental model is this: a stash entry is NOT a branch, NOT a commit on your history, and NOT synced to the remote automatically. It's local scratch space. That makes it ideal for short context switches, but dangerous for anything you want to share with teammates or keep long-term.
People often assume git stash only captures tracked files. It doesn't touch untracked files by default. That silent omission is responsible for a lot of lost work. Use git stash push --include-untracked (or the short form -u) when you have new files that haven't been staged yet.
You can also give stashes a descriptive message with git stash push -m "wip: payment gateway refactor". Without messages, stashes pile up as cryptic stash@{0}, stash@{1} entries and become almost impossible to manage after a long sprint.
- pop deletes the stash from the stack before you resolve conflicts
- If the apply fails, you have no stash backup — the entry is gone
- Use apply when conflicts are possible. Then drop manually after resolving.
- This is one of the most common Git footguns in production.
Managing Multiple Stashes — When One Isn't Enough
Real projects generate real interrupt-driven work. You might be juggling an in-progress feature, an experimental spike, and a half-finished code review all at once. The stash stack can hold all of them — but only if you're disciplined about labelling and retrieving them correctly.
The stack is LIFO (last in, first out), so stash@{0} is always the most recent. If you stash three things without labels, you'll spend five minutes running git stash show -p stash@{2} trying to remember what each one contains. Don't do that to yourself.
To apply a specific stash without popping it — useful for inspecting before committing — use git stash apply stash@{1}. To permanently delete a stash entry you no longer need, use git stash drop stash@{1}. To nuke the entire stash stack: git stash clear. That last command is irreversible, so use it deliberately.
One underused power move: git stash branch <new-branch-name> stash@{0}. This creates a brand new branch from the commit where you originally stashed, then pops the stash onto it. It's the cleanest escape hatch when your stash has grown into something that deserves its own branch rather than a quick pop.
- git stash push -p: interactive hunk-by-hunk selector, like git add -p
- Stash only specific chunks of a file, leave the rest in working directory
- Use when a single file has two unrelated changes you want to separate
- Slow for large changesets — use git stash push -- <path> for file-level control
Git Cherry-Pick — Transplanting Exactly the Commit You Need
Cherry-pick takes one or more commits from anywhere in your Git history and replays them onto your current branch. It doesn't move the original commits — it creates new commits with the same changes but different commit SHAs. Think of it as 'apply this diff' rather than 'merge this branch.'
The most common real-world trigger is a hotfix workflow: a critical bug is fixed on main, and you need that fix on the release/2.4 branch without pulling in the three feature commits that came after it. One git cherry-pick <sha> and you're done.
The second trigger is salvaging work from an abandoned branch. Someone started a feature, it got cancelled, but buried in the commit history is a beautifully written utility function you can reuse. Cherry-pick extracts just that commit.
Crucially, cherry-pick creates a NEW commit SHA on the target branch. The two commits (original and cherry-picked) have the same diff but different identities. This matters for merge conflict detection — Git may not recognise they represent the same change, which can cause duplicate conflicts down the line if those branches ever merge. This is the main reason cherry-pick is a scalpel, not a Swiss Army knife.
- Commit SHA = hash(content + author + timestamp + parent SHA)
- Cherry-pick changes the parent, so the SHA changes even with identical diff
- Same reason rebasing changes SHAs: different parent = different hash
- This is why Git may not recognise cherry-picked commits as the same change during future merges
git cherry-pick --edit <sha> and append (cherry picked from commit abc1234 on main) to the commit message.Handling Cherry-Pick Conflicts and Knowing When Not to Use It
Cherry-pick conflicts happen when the target branch has diverged enough from the source that Git can't cleanly apply the diff. The conflict resolution process is identical to a merge conflict — you edit the files, stage the resolution, then run git cherry-pick --continue. If you decide it's too messy, git cherry-pick --abort restores the branch to its pre-cherry-pick state cleanly.
There's also git cherry-pick --no-commit (or -n), which applies the changes from one or more commits to your working directory and staging area WITHOUT creating a commit. This is perfect when you want to cherry-pick changes from several commits and squash them into one clean commit with a better message.
Now the honest advice about when NOT to cherry-pick: if you find yourself regularly cherry-picking the same fix from one long-lived branch to another, that's a workflow smell. The underlying problem is usually branch strategy — your release branches are too isolated from main, or your hotfix process doesn't feed back into all active branches automatically. Cherry-pick is a patch for a workflow problem, not a solution to it. Use it for one-off emergencies, not as a standing process.
- git cherry-pick <merge-sha> fails: 'is a merge but no -m option was given'
- Use -m 1 to specify parent 1 (main line) as the base
- Use -m 2 to specify parent 2 (merged branch) as the base
- If result is too complex: consider regular merge or rebase instead
Cherry-Pick Without Source Annotation: Duplicate Conflicts During Release Merge
git cherry-pick --edit <sha> and append (cherry picked from commit abc1234 on main) to the commit message.
3. Team convention: added a commit message template that includes a 'Cherry-picked-from:' footer for all cherry-picks.
4. Considered git merge --strategy=ours for the future to let Git know the fix was already applied.- Cherry-pick creates a new SHA. Git does not recognise the cherry-picked commit as the same change during future merges.
- Always annotate cherry-picked commits with the source SHA using --edit. This is critical for debugging and audit trails.
- If you cherry-pick a fix to a release branch and later merge main into that branch, expect a duplicate conflict.
- Cherry-pick is a scalpel for one-off emergencies. If you are cherry-picking the same fix to multiple branches regularly, redesign your branch strategy.
git reflog — find the stash application entry.
3. The stash commit object still exists: git fsck --no-reflogs | grep dangling — find dangling commit objects.
4. Recover: git stash apply <hash> using a hash that looks like your stash.
5. Prevention: use git stash apply when conflicts are possible. Then git stash drop manually after resolving.git log --oneline --all --grep='fix'.
3. Resolve by keeping the existing fix (the cherry-picked version is already on the branch).
4. If this happens regularly: use git merge --strategy=ours to tell Git the changes are already applied.
5. Prevention: always annotate cherry-picks with source SHA for traceability.git stash list — read the messages (this is why you always use -m).
2. If messages are unhelpful: git stash show -p stash@{N} — full diff of each stash.
3. Search stashes for a specific change: git stash show -p stash@{N} | grep 'search-term' for each N.
4. Or: git log --all --oneline --grep='search-term' — stash entries appear in the log.git status to see which files have conflicts.
2. Resolve conflicts in each file — same as merge conflict resolution.
3. Stage resolved files: git add <file>.
4. Continue: git cherry-pick --continue.
5. If too messy: git cherry-pick --abort to return to pre-cherry-pick state.git cherry-pick -m 1 <merge-sha> — parent 1 is the main line.
3. If the result is too complex: consider whether a regular merge or rebase makes more sense.
4. Cherry-picking merge commits is advanced territory — avoid unless you understand the parent structure.Key takeaways
git stash apply over git stash pop whenever a conflict is possibleInterview Questions on This Topic
Frequently Asked Questions
That's Git. Mark it forged?
4 min read · try the examples if you haven't