Switching branches with uncommitted changes that aren’t ready for a commit, Git stops you.

$ git checkout develop
error: Your local changes to the following files would be overwritten by checkout:
	file.txt
Please commit your changes or stash them before you switch branches.
Aborting

git stash saves the working-tree changes onto a temporary stack and resets the working tree to HEAD. The changes aren’t lost; you reapply them later. The commands are simple, but the difference between apply and pop, and what pop does on a conflict, is where mistakes happen.

Basic use

git stash push -m "Working on login feature"   # save with a message
git stash list                                 # see what's stashed
$ git stash list
stash@{0}: On main: Working on login feature

stash@{0} is the most recent; each new stash pushes the existing indices up by one.

git stash saves only changes to tracked files. A new file you haven’t git added yet is excluded, so include it with -u.

git stash -u    # include untracked files too

apply and pop

There are two commands for bringing a stash back.

git stash apply   # apply, leave it on the stack
git stash pop     # apply, remove it from the stack

pop deletes the stash once it applies successfully; apply leaves it. Unless you need to apply the same stash to several branches, pop is the usual choice.

A conflicting pop keeps the stash

pop only removes the stash when the apply succeeds. If a conflict stops the apply from finishing, the stash stays on the stack.

$ git stash pop
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
On branch main
Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
	both modified:   file.txt

no changes added to commit (use "git add" and/or "git commit -a")
The stash entry is kept in case you need it again.

The last line, The stash entry is kept, states the behavior. It’s still in the list.

$ git stash list
stash@{0}: On main: my work

After resolving the conflict and running git add, it’s easy to assume the stash was cleaned up too. But stash@{0} is still there, and the next pop applies the already-merged changes a second time. The sequence after a conflict is:

# 1. Resolve the conflict markers (<<<<<<<, =======, >>>>>>>)
# 2. git add file.txt
# 3. git stash drop   # pop didn't remove it, so do it manually

With no conflict, pop removes the stash and step 3 is unnecessary.

Inspecting a stash first

When there are several stashes, or the contents aren’t obvious, check before applying.

git stash show -p          # detailed diff
$ git stash show -p
diff --git a/app.js b/app.js
index de98044..f4b382e 100644
--- a/app.js
+++ b/app.js
@@ -1,3 +1,4 @@
 a
-b
+b modified
 c
+d added

Without -p you get only the list of changed files.

Two examples

When an urgent fix lands mid-feature, save the work and switch branches.

git stash push -m "Working on feature/login"
git checkout hotfix/critical-bug
# fix and commit
git checkout feature/login
git stash pop

Pulling remote changes on top of uncommitted work follows the same pattern.

git stash
git pull origin main
git stash pop   # on conflict, resolve, then git stash drop

In both cases a conflict on that final pop leaves the stash behind, so you drop it yourself.