Git Stash: A Practical Beginner's Guide
5 min read Git, Version control, CLI
git stash takes the changes you haven’t committed yet, puts them on a shelf, and gives you a clean working tree. Later you take them off the shelf and carry on. That’s it. You don’t need a throwaway commit, and nothing lands in your history.
I don’t use it every day, and I’d say that’s how it should be. But when I need it, nothing else does the job as cleanly. This guide covers the situations where it actually saved me, plus the handful of flags I wish someone had told me about earlier.
What git stash actually saves
By default, git stash saves:
- changes to tracked files that you haven’t staged yet
- changes you have staged with
git add
It does not save:
- untracked files (new files Git has never seen)
- ignored files
That second list catches everyone at least once. You stash, switch branches, and your new file is still sitting there. See stashing untracked files below.
Use case 1: stashing before you switch branches
Say you’re on a feature branch called user-profile, halfway through changes across a few files. Then someone pings you: there’s a bug on main and it needs fixing now.
You don’t want to commit half-done work and clutter your history. So stash it:
git stash
Your working tree is clean again. Switch to main, fix the bug, commit, push. Then come back and restore your work:
git switch user-profile
git stash pop
git stash popapplies the stash and removes it from the stash list.git stash applyapplies it but keeps it, which is handy if you want the same changes on more than one branch.
Use case 2: keeping several stashes with names
Sometimes you’ve got two half-finished things going. Stash each one with a message so you can tell them apart later:
git stash push -m "Task: implement payment gateway"
git stash push -m "Feat: table view in dashboard"
You’ll see older tutorials (including an older version of this post) use
git stash save "message". That still works, but it’s deprecated.git stash push -mis the current way, and it also lets you stash specific files.
Now list them:
git stash list
stash@{0}: On user-profile: Feat: table view in dashboard
stash@{1}: On user-profile: Task: implement payment gateway
The newest stash is always stash@{0}. To bring back a specific one, use its index:
git stash apply stash@{1}
Or find it by a word in its message, so you don’t have to count:
git stash apply "stash^{/payment}"
The quotes matter. zsh and PowerShell both do their own thing with curly braces, and you’ll get a confusing error without them.
Use case 3: stashing when a pull conflicts
This happened to me a few times while building the Moksha Innovision website with my teammate Harsh. We’d both be editing the same files, I’d try to git pull, and Git would refuse because my local changes would be overwritten.
The fix is to stash, pull, then put your changes back:
git stash
git pull origin main
git stash pop
If your changes and the pulled changes touch the same lines, pop stops with a conflict, just like a merge. Open the files, fix the conflict markers, then:
git add .
git stash drop
When
git stash pophits a conflict, it does not drop the stash, so your changes are still safe on the shelf. That’s why you drop it yourself once everything’s resolved.
If you do this dance a lot, Git can do it for you:
git pull --rebase --autostash
Or turn it on for good:
git config --global rebase.autoStash true
Stashing untracked files
As mentioned, new files aren’t stashed by default. Add -u (short for --include-untracked):
git stash -u
If you also want ignored files (build output, .env, and so on), use -a (--all). I rarely want that, so be careful with it.
Stashing only some files
You don’t have to stash everything. Pass paths after --:
git stash push -m "only the api changes" -- src/api/
Or pick changes interactively, hunk by hunk:
git stash -p
On Git 2.35 and newer, you can also stash just what’s staged:
git stash push --staged
Looking inside a stash before applying it
Not sure what’s in stash@{1}? Check before you apply it:
git stash show stash@{1} # which files changed
git stash show -p stash@{1} # the full diff
Turning a stash into a branch
If the stash turns out to be a real piece of work, make it a branch:
git stash branch payment-gateway stash@{1}
This creates a branch from the commit you were on when you stashed, applies the stash there, and drops it if everything applies cleanly. It’s also the easiest way out when a stash won’t apply on your current branch because too much has changed.
Cleaning up
Stashes pile up quietly. Every now and then, clean them out:
git stash drop stash@{0} # remove one
git stash clear # remove all of them
git stash cleardoesn’t ask for confirmation. Rungit stash listfirst.
Recovering a stash you dropped by accident
It happens. A dropped stash is still a commit object for a while. It’s just not referenced anymore. You can usually find it:
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
Check the hashes with git show <hash> until you find yours, then:
git stash apply <hash>
Quick reference
| Command | What it does |
|---|---|
git stash | Stash tracked changes (staged and unstaged) |
git stash push -m "msg" | Stash with a name |
git stash -u | Also stash untracked files |
git stash list | Show all stashes |
git stash show -p stash@{n} | Show the diff of a stash |
git stash apply stash@{n} | Apply a stash, keep it in the list |
git stash pop | Apply the latest stash and remove it |
git stash branch <name> | Create a branch from a stash |
git stash drop stash@{n} | Delete one stash |
git stash clear | Delete every stash |
When not to use stash
A stash is a shelf, not storage. If you’re parking work for more than a day or two, a work-in-progress commit on its own branch is safer. It has a name, it shows up in git log, and you can push it. If you regularly need two branches checked out at once, look at git worktree instead.
For the quick “hold on, I need to do something else first” moments, though, git stash is exactly the right tool.
Keep reading
All posts4 min read
How to Customize the GRUB Theme on Fedora
Change the GRUB2 boot menu theme on Fedora step by step: install a theme, edit /etc/default/grub, regenerate grub.cfg, and fix the usual problems.

8 min read
My Windows PowerShell Setup: Oh My Posh, Nerd Fonts and Autocomplete
How I set up Windows Terminal and PowerShell: Scoop, a Nerd Font, an Oh My Posh prompt, Terminal-Icons, PSReadLine autocomplete and handy profile functions.
