Stashing work in progress
How to shelve half-done changes with git stash so you can switch branches instantly, then pick up exactly where you left off.
What you'll learn
- How git stash saves your working directory and index to a temporary stack — without creating a commit
- The difference between git stash pop and git stash apply, and when to choose each
- Why plain git stash silently ignores untracked files: use -u to include them
Before you start
Why not just commit?
A half-done feature commit pollutes your history with a message like “WIP do not merge.” When you eventually push, that noise is permanent. A stash, by contrast, is local-only — it never leaves your machine unless you explicitly export it — and it carries no commit SHA in your branch history. Think of it as a personal sticky note on your desk, not a page in the permanent record.
The stash as a stack
Git stores stashes in a LIFO stack (last in, first out). Every time you run git stash, a new entry is pushed on top. Every time you pop, the top entry is removed. The entries are numbered stash@{0} (top), stash@{1}, stash@{2}, and so on. The number always reflects position in the stack at that moment — if you drop stash@{1}, what was stash@{2} becomes stash@{1}.
The typical flow
Here is the complete stash-switch-fix-return cycle you will use most often.
# You are on feature/payments, mid-change
git stash # shelf everything, restore a clean working dir
git switch hotfix/null-check # switch freely — working dir is clean
# ... make the urgent fix, commit it ...
git switch feature/payments # back to your branch
git stash pop # restore your stashed work and remove it from the stack
After git stash, your working directory looks exactly as it did after your last commit. After git stash pop, it looks exactly as it did before you stashed.
The flow below shows the stash stack during this sequence.
Core commands
Stash and inspect
git stash # stash tracked, modified files (index + working tree)
git stash list # view the whole stack
stash@{0}: WIP on feature/payments: 3f1a8c2 Add cart total
stash@{1}: WIP on feature/payments: 3f1a8c2 Add cart total
Each entry shows the branch it came from and the commit it was made against. Without names they can blur together fast — see Named stashes below.
Restore: pop vs apply
git stash pop # apply stash@{0}, then DROP it from the stack
git stash apply # apply stash@{0}, but KEEP it on the stack
Use pop when you are done with the stash and want the stack clean. Use apply when you want to replay the same changes on multiple branches — or when you are nervous and want the stash as a backup until you confirm everything looks right.
Include untracked files
Named stashes
When the stack grows past one entry, stash@{0} tells you nothing useful. Name them:
git stash push -m "payments: wip cart subtotal logic"
git stash push -m "payments: experiment with tax rounding"
git stash list
stash@{0}: On feature/payments: payments: experiment with tax rounding
stash@{1}: On feature/payments: payments: wip cart subtotal logic
Apply or drop a specific entry by its index:
git stash apply stash@{1} # apply without dropping
git stash drop stash@{1} # drop one entry
git stash clear # drop every entry — no undo
Quick reference
| Command | What it does |
|---|---|
git stash | Shelf tracked modifications, restore clean working dir |
git stash -u | Same, plus untracked files |
git stash push -m "msg" | Stash with a descriptive name |
git stash list | Show the full stack |
git stash pop | Apply top entry and remove it from stack |
git stash apply | Apply top entry, leave it on stack |
git stash drop stash@{n} | Remove one specific entry |
git stash clear | Wipe the entire stack |