Git commands
Where stashed changes really go
git stash: a drawer for half-finished work
How to use this page
- slider / ▶Drag the slider, or press play, to watch the command happen. Before and After jump to either end.
- ← → · spaceStep through a multi-step command; space toggles Before / After.
- APlay or pause the loop (the page opens playing). Any manual input takes over.
- hoverA commit shows its message, author, date and parents, with its history highlighted.
- clickCopies the commit sha.
- ctrl + wheelZoom around the cursor (pinch on a trackpad). Double-click resets the view.
- EscStop playback, reset the view, close this menu.
- shareThe Share button copies a link to this graph, copies it as an image, downloads PNG/SVG/page, or posts it. #before, #after or #step=N in the link pins the state.
git-sim visually simulates any Git command in your own repos - from your terminal, IDE, or AI.
Table of Contents
- Introduction
- What is git stash?
- Watch it happen
- Before and after
- What a stash is
- Is it safe?
- Useful forms
- How to undo it
- Try it on your repository
- Common questions
- Summary
- Next steps
- Related commands
Introduction
You're halfway through something and need a clean working directory right now: to switch branches, to pull, to check whether a bug exists without your changes. git stash puts your uncommitted work somewhere safe and gives you a clean tree. It's presented as a separate feature, but under the hood a stash is just a commit that no branch points at.
In this article, we'll:
- Watch
git stashclear the working directory and staging area - See which changes it takes and which it leaves behind
- Look at what a stash entry actually is
What is git stash?
git stash records your staged and unstaged changes to tracked files as a commit (two commits, in fact: one for the index and one for the working tree), stores a reference to it in refs/stash, and then resets your working directory and staging area to match HEAD. Untracked files are left alone unless you ask for them.
Watch it happen
Our sample repo has a modified file and a staged file to set aside, plus an untracked file. Here's git stash:
- Before:
README.mdhas a staged change andapp.pyis modified in the working directory.HEADis attached tomainat8c02d5b. - Git saves both changes in a new stash entry,
stash@{0}, and resets the working directory and staging area to match8c02d5b. mainandHEADdon't move. The stash entry is stored underrefs/stash, and the untrackednotes.txt(not drawn here) is left where it was.
Before and after
git status --short before:
M README.md
M app.py
?? notes.txt
and after:
?? notes.txt
git stash list now shows one entry, named after the commit you were on:
The raw git output, if you want to read along in text
git log --oneline --graph --all
before
* 1117a34 (feature) Add search tests
* e5869f0 Fix typo in search box
* fc19889 Add search box
| * 8c02d5b (HEAD -> main) Update dependencies
| * a0b2db3 Add user settings page
|/
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commitafter
* a827e22 (refs/stash) WIP on main: 8c02d5b Update dependencies
|\
| * e6cd7fc index on main: 8c02d5b Update dependencies
|/
* 8c02d5b (HEAD -> main) Update dependencies
* a0b2db3 Add user settings page
| * 1117a34 (feature) Add search tests
| * e5869f0 Fix typo in search box
| * fc19889 Add search box
|/
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commitwhat git printed
Saved working directory and index state WIP on main: 8c02d5b Update dependenciesWhat a stash is
Run git log --oneline -g refs/stash or git show stash@{0} and you'll find an ordinary commit with a message like "WIP on main: 8c02d5b Update dependencies", whose parents are HEAD and a second commit holding the index state. It isn't on any branch, which is why git log doesn't show it, but it's in the object database like everything else.
refs/stash keeps them, and I stopped using stash for anything I'd want in a week, because a real commit on a branch with a name is easier to find than stash@{7}.
Is it safe?
Safe git-sim pre-flight
Stashes current changes; recoverable via git stash pop.
The changes are stored as commits before your working directory is reset, so stash can't lose tracked changes. The one thing to remember is that untracked files aren't included unless you add -u (Pro Git's Stashing and Cleaning chapter shows it).
Useful forms
git stash -uincludes untracked files.git stash push -m "message"names the entry.git stash push <file>stashes only some files.git stash list,show,pop,apply,dropmanage the stack.pophas its own page.
How to undo it
git stash pop
restores the changes and removes the entry. (Staged changes come back as unstaged unless you use --index.)
Try it on your repository
pip install git-sim
git-sim stash
git-sim shows which files would move into the stash, from the working directory and the staging area.
Common questions
What does git stash do?
It saves your uncommitted changes to tracked files as a commit under refs/stash and resets your working directory and staging area to HEAD.
Does git stash include untracked files?
Not by default. git stash -u includes them, and -a includes ignored files too.
Where are stashed changes stored?
As commits in the object database, referenced from .git/refs/stash and its reflog. git stash list reads that reflog.
Can I lose a stash?
Only by dropping it and then waiting for garbage collection. Even a dropped stash's commit can be recovered by hash for a while.
Summary
In this article, we watched git stash take a staged and an unstaged change into a hidden commit while leaving an untracked file behind, and looked at what a stash entry actually is.
Next steps
git stash pop brings the changes back. If you find yourself stashing to switch branches often, git worktree add may fit better.
Related commands
- git stash pop, to restore and drop the entry
- git status, shows what a stash would take
- git worktree add, the alternative for switching branches
- git restore, to discard instead of stash
- git checkout, the usual reason to stash
- git commit, often the better choice
- git stash -u, to stash untracked files too
