You ran git stash, switched to main to review a PR, switched back to your feature branch with git checkout feature/login, ran git stash pop — and nothing happened, or pop applied to the wrong working tree state and then dropped the stash. Now git stash list is empty and your half-finished changes are nowhere to be found. Stashes are stored as special commits in .git/refs/stash; dropping, popping, or clearing them removes the ref but the underlying commit objects persist in the reflog for 30 days. Recovery is almost always possible.
Common causes
Ordered by hit rate, highest first.
1. git stash pop applied and dropped the stash automatically
git stash pop is equivalent to git stash apply + git stash drop. If the apply succeeded without conflicts, the stash entry was removed immediately. The changes are on disk in the working tree — they were not “lost,” just applied.
How to spot it: Run git diff and git status. If you see modified files, the stash was applied successfully and nothing is lost.
2. git stash drop or git stash clear run by mistake
A copy-paste error, muscle memory, or a terminal shortcut ran git stash drop instead of git stash show. git stash clear removes all stash entries at once.
How to spot it: git reflog show refs/stash — this shows the full history of the stash reference, including all entries that were dropped.
3. git stash pop conflicted and partially applied
Pop hit a merge conflict, left the stash applied in a conflicted state, and dropped the stash entry (behavior depends on Git version). In some versions the stash is kept; in others it is dropped on first conflict.
How to spot it: git status shows “both modified” entries. git stash list is empty but there are unresolved conflict markers in the working tree.
4. Stash was on a different branch than expected
You stashed on feature/login, forgot, switched to feature/payments, and created a second stash there. When you switch back, git stash list shows the payments stash at the top (stash@{0}) and the login stash at stash@{1}, leading you to pop the wrong one.
How to spot it: git stash list shows entries with their branch names in the message: stash@{0}: WIP on feature/payments: ....
5. Worktree or bare clone has no stash ref
If you are working inside a git worktree that was added after stashing on the main worktree, the refs/stash from the main worktree is not visible inside the added worktree.
How to spot it: git worktree list shows multiple entries. The stash was created in a different worktree’s context.
6. git clean -fd removed untracked files that the stash held
git stash by default stashes only tracked modified files. Untracked new files are not stashed unless you use -u or -a. Running git clean -fd after stashing removes those untracked files permanently.
How to spot it: Your missing work consisted of new files that were never git add-ed.
Shortest path to fix
Step 1: Check whether the stash was already applied to the working tree
git status
git diff
If you see your changes, they are already applied — no further action needed.
Step 2: Find dropped stash commits in the reflog
git reflog show refs/stash --date=iso
If the stash was dropped, it will still appear in this log for up to 30 days. Note the SHA (call it STASH_SHA).
If refs/stash reflog is empty, try:
git fsck --unreachable | grep commit | awk '{print $3}' | while read sha; do
git show --stat "$sha" 2>/dev/null | head -3
echo "---"
done | grep -B2 "WIP"
Step 3: Restore the stash to the working tree
# Apply the recovered stash SHA directly
git stash apply STASH_SHA
Or to re-add it as a proper stash entry first:
git update-ref refs/stash STASH_SHA -m "restore dropped stash"
git stash pop
Step 4: Handle a pop that left conflicts
# Resolve each conflict file, then stage it
git add src/login.ts
# After resolving all conflicts, drop the stash entry manually
git stash drop
Step 5: Recover untracked files (if git clean was run)
Untracked files removed by git clean are generally unrecoverable through Git unless your IDE has local history (VS Code timeline, JetBrains Local History) or a filesystem snapshot (Time Machine, ZFS snapshot).
# Check IDE local history before concluding the files are gone
# VS Code: right-click file in explorer > Timeline > select a local history entry
Prevention
- Prefer
git stash applyovergit stash pop— apply does not drop the stash, so you keep it as a safety net even after applying. - Name your stashes:
git stash push -m "login form WIP — session token handling"sogit stash listis readable. - Always stash with
git stash push -uto include untracked files, or usegit stash push -afor both untracked and ignored files. - Before running
git clean, do a dry run:git clean -nfdshows what would be deleted without actually deleting. - Use
git worktree addto work on multiple branches simultaneously instead of stash-checkout-stash cycles. - Configure your IDE to keep local history for at least 7 days as a secondary recovery option.
- Consider committing WIP changes as
git commit -m "WIP: do not merge"instead of stashing — commits survive much longer and are easier to find viagit log.
FAQ
Q: Can I recover a stash that was dropped more than 30 days ago?
A: Possibly, if git gc has not pruned the objects yet. Run git fsck --lost-found — all dangling commits are written to .git/lost-found/commit/. Inspect each SHA with git show to find your stash object.
Q: How do I tell which stash belongs to which branch when git stash list shows many entries?
A: Each stash entry includes the branch name: stash@{2}: WIP on feature/login: abc1234 add session token. You can also run git stash show stash@{2} to see the diff.
Q: Is there a way to see the full diff of a stash without applying it?
A: Yes: git stash show -p stash@{0} shows the full patch diff. Add --stat instead of -p for a summary.
Q: We use a shared stash convention in our team — is there a better tool?
A: Stashes are local only and never pushed to the remote. For sharing WIP across machines, commit to a personal draft branch (git switch -c draft/my-feature) and push it to your fork.