How can I recover a dropped stash in Git?
I frequently use git stash and git stash pop to save and restore changes in my working tree. Yesterday, I had some changes in my working tree that I had stashed and popped, and then I made more changes to my working tree. I’d like to go back and review yesterday’s stashed changes, but git stash pop appears to remove all references to the associated commit.
I know that if I use git stash then .git/refs/stash contains the reference of the commit used to create the stash. And .git/logs/refs/stash contains the whole stash. But those references are gone after git stash pop. I know that the commit is still in my repository somewhere, but I don’t know what it was.
Is there an easy way to recover yesterday’s stash commit reference?
Recovering a dropped Git stash is often possible using Git’s built-in history tracking tools. When you use git stash pop, the stash reference is removed from the stash list but the actual commit typically remains in your repository’s object database, making recovery feasible through several methods.
Contents
- Understanding Git Stash Behavior
- Recovering Dropped Stashes Using Reflog
- Finding Orphaned Stash Commits with fsck
- Using Git Log and Gitk for Recovery
- Prevention and Best Practices
- Alternative Recovery Methods
Understanding Git Stash Behavior
When you use git stash, Git creates a commit object that stores your changes and adds a reference to it in .git/refs/stash. This commit object contains:
- The changes from your working directory
- A reference to the commit you were on when you stashed
- A parent commit that points to the previous stash
The key insight is that when you use git stash pop, Git only removes the reference from the stash list and applies the changes to your working directory. The actual commit object usually remains in the repository’s object database unless garbage collection has cleaned it up.
💡 Important: Garbage collection can permanently remove unreferenced commits. Run
git gcless frequently and avoidgit gc --aggressiveto prevent accidental loss of dropped stashes.
Recovering Dropped Stashes Using Reflog
The reflog (reference log) is your most powerful tool for recovering dropped stashes. Git maintains a log of changes to branch tips, including stash references.
Step-by-Step Reflog Recovery:
-
Check the reflog for stash entries:
bashgit reflog show stash
-
Look for stash-related entries in the output. You’ll see entries like:
6a4b2f3 stash@{0}: drop: WIP on feature-branch: abc1234 Add new functionality -
Recreate the stash reference from the commit hash:
bashgit update-ref refs/stash 6a4b2f3
-
Verify the recovery:
bashgit stash list
If the reflog doesn’t show stash entries, try checking the main branch reflog:
git reflog
Look for entries around the time you popped the stash. The commit hash in the reflog entry corresponds to the stash commit.
Finding Orphaned Stash Commits with fsck
When a stash is dropped, its commit becomes “dangling” - it exists but isn’t referenced by anything. Git’s fsck (file system check) can find these orphaned objects.
Using fsck to Recover Stashes:
-
Find all dangling commits:
bashgit fsck --dangling
-
Look for stash-related dangling commits. They’ll appear as:
dangling commit 6a4b2f3 stash@{0}: WIP on feature-branch: abc1234 Add new functionality -
Create a new stash reference from the commit hash:
bashgit update-ref refs/stash 6a4b2f3
-
Double-check with:
bashgit stash show stash@{0}
Note that git fsck --dangling may show many objects. You can filter for stash-related ones by looking for commit messages containing “WIP” (Work In Progress) or “stash”.
Using Git Log and Gitk for Recovery
Visual Recovery with Gitk
The gitk graphical tool can help visualize commit history and find dropped stashes:
gitk --all
In gitk:
- Look for commits with “WIP” in the message
- Check the parent-child relationships
- Identify which commit represents your dropped stash
- Note the commit hash
Command-Line Log Search
You can also search through commit history:
git log --grep="WIP" --oneline
Or more broadly search for stash-related commits:
git log --all --grep="stash" --oneline
Once you identify the commit hash, recreate the stash reference:
git update-ref refs/stash <commit-hash>
Prevention and Best Practices
Better Stash Management
Instead of relying on recovery, consider these preventive measures:
-
Use descriptive stash names:
bashgit stash push -m "Feature X: Add user authentication" -
List stashes before popping:
bashgit stash list git stash pop stash@{2} -
Use
git stash applyinstead ofpopwhen unsure:bashgit stash apply stash@{0} -
Create branches for important work:
bashgit checkout -b temp-branch # work on changes # return to main branch when ready
Configure Git for Better Stash Handling
Add this to your .gitconfig:
[alias]
stash-pop = !git stash list && echo "Which stash to pop? (stash@{n})" && read stash && git stash pop $stash
This forces you to see available stashes before popping one.
Alternative Recovery Methods
Using Bisect to Find the Stash Commit
If other methods fail, you can use git bisect to narrow down when the stash commit was created:
-
Start a bisect session:
bashgit bisect start
-
Mark a known good commit (before you created the stash):
bashgit bisect good abc1234
-
Mark a known bad commit (after you popped the stash):
bashgit bisect bad def5678
-
Git will guide you through commits to find the stash.
Manual Object Database Search
For advanced recovery, you can manually search the object database:
find .git/objects -type f | while read obj; do
git cat-file -p $(basename $obj | tr '[:lower:]' '[:upper:]') 2>/dev/null | grep -q "WIP" && echo "Found: $obj"
done
This searches through all Git objects for those containing “WIP” in their content.
Sources
- Official Git Documentation - Stash
- Pro Git Book - Stashing
- Git Reflog Documentation
- Git Fsck Documentation
- Stack Overflow - Recovering dropped git stash
Conclusion
Recovering a dropped Git stash is usually possible when you act quickly before garbage collection removes the orphaned commit. The reflog method is your most reliable approach, followed by fsck for finding dangling commits. Always use descriptive stash names and consider using git stash apply instead of pop to prevent accidental loss.
Key takeaways:
- Check
git reflog show stashfirst for dropped stash references - Use
git fsck --danglingto find orphaned stash commits - Recreate stash references with
git update-ref refs/stash <commit-hash> - Prevent future losses with descriptive stash names and careful stash management
If you frequently work with stashes, consider setting up alias commands or using GUI tools that provide better stash management interfaces to minimize the risk of accidental drops.