All posts
·12 min read· stash· git· merge-conflicts· undo· recovery

Undo a git stash pop that caused a conflict (without losing the stash)

You ran git stash pop and got conflict markers everywhere. Good news: a conflicted pop does not drop your stash. Here is how to undo the pop or resolve it, with verified commands.

You stashed your work. Then you pulled the latest main. Then you ran git stash pop to bring your changes back. Instead of your code returning quietly, the terminal said this:

Auto-merging config.js
CONFLICT (content): Merge conflict in config.js

Now config.js is full of <<<<<<<, =======, and >>>>>>> markers. Your other files look half-applied. git status is red. And the worst thought hits you: did I just lose my stash? You popped it, the pop failed, so maybe the stash is gone and your changes are stuck in this broken state forever.

Stop. Take a breath. You have not lost anything.

This is one of the most common scares in Git, and the panic comes from a misunderstanding of what git stash pop does when it hits a conflict. The truth is the opposite of what it feels like: a conflicted pop does not drop your stash. Your stash is still sitting in the stash list, exactly as it was. You have a clean way back, and you have a clean way forward. This post shows both, with commands verified against the official Git docs.

The one fact that saves you

Here is the fact to hold onto, straight from the git-stash docs:

"Applying the state can fail with conflicts; in this case, it is not removed from the stash list. You need to resolve the conflicts by hand and call git stash drop manually afterwards."

Read that twice. When git stash pop runs into a conflict, Git does not remove the stash from the list. It stays there.

This makes sense once you see what pop is built to do. The docs describe git stash pop as two steps: apply the stash, then drop it. The drop only happens on a clean apply. If applying the stash produces a conflict, the second step never runs. Git stops, hands you the conflict to resolve, and leaves the stash entry in place as a safety net.

So the situation you are actually in is:

You can confirm this yourself right now:

git stash list
stash@{0}: WIP on main: 3c4f1a2 add config loader

There it is. Your stash. Still safe. Whatever you do next, you have not lost the snapshot. That single line is the difference between a five-minute fix and an afternoon of dread.

You have two choices

From here, you can go in one of two directions. Both are safe.

  1. Resolve and keep. Push through the conflict — edit the files, remove the markers, keep the merged result. This is the right path when the conflict is small and you want your stashed work in your tree right now.
  2. Undo the pop entirely. Throw away the half-applied, conflicted state and return your working tree to clean HEAD. Your stash is still in the list, so you can try again later — ideally with git stash apply, which we will get to. This is the right path when the conflict is bigger than you expected, or you popped on the wrong branch, or you just want to start over.

Pick based on the situation. Let's walk through each one with exact commands.

Path 1: Resolve the conflict and keep your work

A conflicted stash pop is, mechanically, just a merge conflict. The markers mean the same thing they always do, and you resolve them the same way. We have a full walkthrough of reading and resolving conflict markers in How to resolve merge conflicts in Git — read that for the base/ours/theirs model and the marker syntax. Here is the short version applied to a stash pop.

Step 1: See what conflicted

git status
On branch main
Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   config.js

The phrase both modified marks your conflicted files. Everything else from the stash applied cleanly.

Step 2: Edit each conflicted file

Open config.js. Find each block of <<<<<<< / ======= / >>>>>>> markers. Decide what survives — your stashed change, the version already in your tree, or a combination. Remove all three marker lines. Make the result valid code.

Step 3: Mark each file resolved

git add config.js

Here git add does not mean "stage a new feature." It means "I have settled this file."

Step 4: Drop the stash yourself

This is the step people miss. Because the pop hit a conflict, Git did not drop the stash for you. It is still in the list. Once you are happy with the resolution, remove it by hand — exactly as the docs instruct:

git stash list          # confirm it's still there
git stash drop          # remove the top stash (stash@{0})

If you skip this, no harm is done — you just have a stale stash entry hanging around. But cleaning it up keeps git stash list honest. To drop a specific one: git stash drop stash@{1}.

That's Path 1. Resolve, git add, then git stash drop. Your work is in your tree and the stash list is clean.

Path 2: Undo the pop and start over

Sometimes you look at the conflict and decide you do not want to deal with it right now. Maybe you popped onto the wrong branch. Maybe the conflict is huge. Maybe you just want your working tree back the way it was before you typed git stash pop.

You can do that. The half-applied changes are only in your working tree (and index), and your stash is still in the list. So if you discard the working-tree changes, you lose nothing — the stash is the source of truth and it's intact.

The command, and why the obvious one is not enough

The instinct is to reach for git restore . or git checkout -- . to "throw away my changes." Be careful here — these have a subtlety that matters in exactly this situation.

The git-restore docs say the default restore source is the index, not HEAD: "the contents are restored from HEAD if --staged is given, otherwise from the index." A plain git restore . (or git checkout -- .) restores your working tree from the index — but after a conflicted pop, your index is not clean either. Stages and conflict entries are sitting in it. So restoring from the index can leave you in a still-messy state, not back at clean HEAD.

To fully back out, you want to reset both the working tree and the index to match HEAD. The precise command, verified against the git-restore docs:

git restore --source=HEAD --staged --worktree .

Reading the flags against the docs: --staged restores the index, --worktree (-W) restores the working tree, and --source=HEAD makes HEAD the content both are restored from. The docs note that when --staged is given the default source is already HEAD — but passing --source=HEAD explicitly makes the intent unmistakable and is safe to include. After this, your working tree and index match your last commit. The conflict markers are gone. The half-applied stash is gone from your tree.

And your stash is still in the list:

git stash list
stash@{0}: WIP on main: 3c4f1a2 add config loader

If you had things staged before you popped

If you had your own changes staged in the index before you ran git stash pop, the command above will discard those staged changes too, because it restores the index from HEAD. If you want to keep them, that is a different, more careful situation — and honestly, the cleanest move is to commit or stash those changes first, then deal with the pop. Don't fight Git here; give it a clean tree to work with.

The blunt instrument: git reset --hard

You will see git reset --hard recommended for this all over the web, and it does work — it returns the working tree and index to HEAD. But understand exactly what it does first. The git-reset docs describe --hard as: "Overwrite all files and directories with the version from <commit>... Tracked files not in <commit> are removed so that the working tree matches <commit>."

That is the warning. git reset --hard discards ALL uncommitted work, not just the conflicted pop. If you had other edits in your tree that were nothing to do with the stash, they are gone too. There is no "only the conflict" about it — it flattens everything back to HEAD.

git reset --hard          # resets to HEAD; throws away ALL uncommitted changes

Use this only when you are certain the only uncommitted thing in your tree is the failed pop. If in doubt, the targeted git restore --source=HEAD --staged --worktree . is the safer choice because its scope is at least explicit. Either way, your stash survives — reset --hard touches the working tree and index, not the stash list.

Why git stash apply is safer than git stash pop

Here is the lesson the whole episode teaches. Once you have backed out (or resolved) the pop, you may want to try applying the stash again. Use git stash apply, not git stash pop.

The difference is small in wording and large in consequence. The git-stash docs define them like this:

pop removes the stash on a clean apply. apply never removes it. That makes apply non-destructive: you can run it, see what happens, and if you don't like the result — conflict or otherwise — back out and try again, because the stash is guaranteed to still be there.

git stash apply           # apply the stash, keep it in the list no matter what

With apply, retrying is free. You hit a conflict, you back out with git restore --source=HEAD --staged --worktree ., you try a different branch or a different base, you apply again. The stash is your fixed reference point through all of it. When you finally get a clean result you're happy with, drop it by hand: git stash drop.

The only thing pop buys you over apply is one less git stash drop later, and only when the apply is clean. That convenience is not worth the moment of panic when a pop conflicts and you don't yet know the stash survived. Many people switch to apply + manual drop as their default for exactly this reason.

A clean recovery recipe

Save this. Next time git stash pop throws a conflict, follow these steps in order.

  1. Don't panic, and confirm the stash is safe.

    git stash list
    

    Your stash is still there. A conflicted pop never drops it.

  2. Decide: resolve, or back out? Small conflict and you want the work now → resolve. Big conflict, wrong branch, or you want a clean retry → back out.

3a. To resolve: edit each both modified file, remove the markers, then:

git add <file>
git stash drop            # remove the stash you no longer need

3b. To back out: discard the half-applied changes:

git restore --source=HEAD --staged --worktree .

(Or git reset --hard if you are sure the failed pop is the only uncommitted thing in your tree. It is more destructive.)

  1. Retry safely with apply, not pop:

    git stash apply
    

    Now the stash stays in the list whatever happens, so you can keep trying.

  2. When you're happy, clean up:

    git stash drop
    

You can practise this exact situation in the Stash Pop Caused a Conflict scenario — a live terminal with a seeded pop conflict where you resolve, add, and drop with no real repo at risk.

Common myths

Three things people believe about a conflicted stash pop that are wrong.

Myth 1: "A conflicted pop loses my stash." False, and this is the big one. The git-stash docs state plainly that when applying the stash "can fail with conflicts... it is not removed from the stash list." The pop drops the stash only after a clean apply. A conflict stops the operation before the drop step, so your stash stays put. Run git stash list to prove it to yourself. You have not lost the snapshot — you can always back out and try again.

Myth 2: "pop and apply are the same command with different names." No. They differ in one decisive way. pop removes the stash from the list after applying; apply "do[es] not remove the state from the stash list," per the docs. On a clean apply that difference is cosmetic. On a conflict it is everything: with apply you always have the stash to retry from, with no doubt about whether it survived. That is why apply is the safer default for risky stashes.

Myth 3: "I have to resolve the conflict before I can do anything else." No. A conflicted pop is not a trap you must fight your way out of. You can back out completely — restore your working tree and index to HEAD with git restore --source=HEAD --staged --worktree . — and walk away. The conflict markers vanish, your tree is clean, and your stash is still in the list for later. Resolving is one option, not an obligation.

What to read next

A conflicted stash pop sits next to a few other "this feels worse than it is" Git moments. These cover the rest:

When you want to do this with your hands instead of reading about it, the Stash as Temporary Undo lesson opens a live terminal where stashing, popping, and dropping all happen against a real tree. Park your work, bring it back, and watch the stash list behave exactly as the docs promise.