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.