Learning Objectives
By the end of this lesson you will be able to:
- Choose correctly between
git stash popandgit stash apply - Restore a specific stash rather than the most recent one
- Handle a conflict that occurs while restoring a stash
- Clean up the stash stack without deleting something you needed
The Three Commands
| Command | Restores the changes | Removes the stash entry |
|---|---|---|
git stash apply |
Yes | No |
git stash pop |
Yes | Yes |
git stash drop |
No | Yes |
That table is the entire lesson. Everything below is detail.
pop: The Everyday One
git stash pop
On branch test/fixture-rewrite
Changes not staged for commit:
modified: tests/fixtures/user.js
modified: config/test-env.yaml
Dropped refs/stash@{0} (a1b2c3d4e5f6...)
Restores the most recent stash and removes it from the stack. This is what you want after a short interruption: the pocket is emptied because the work is back where it belongs.
One caveat worth knowing: pop restores your changes as unstaged, even if some of them were staged when you stashed. If you care about the staging state, use --index:
git stash pop --index
apply: The Careful One
git stash apply
Same restoration, but the stash entry stays on the stack.
Use apply when:
- You want the same changes on more than one branch. Apply to one, test, switch, apply again.
- You're not certain the restore will go smoothly. If it lands badly, the stash is still there as a safety net.
- You're restoring onto a branch that has moved a lot since you stashed. If the result is a mess,
git restore .and try again somewhere else.
The cost is that the stash stays until you deal with it, which is how stacks of ten forgotten stashes accumulate.
Restoring a Specific Stash
Both commands default to stash@{0}. Name another explicitly:
git stash list
git stash apply stash@{2}
git stash pop stash@{1}
Always run git stash list first. Indices shift every time you push a new stash, and popping the wrong one is a genuinely annoying way to spend ten minutes.
When Restoring Conflicts
A stash restore is a merge. If the branch changed the same lines your stashed work changed, you get a conflict:
Auto-merging config/test-env.yaml
CONFLICT (content): Merge conflict in config/test-env.yaml
The markers are identical to Module 3's, and so is the resolution: edit, remove markers, git add.
The important detail: when pop hits a conflict, the stash entry is not dropped. Git leaves it in place precisely because the restore did not fully succeed. So after you resolve the conflict, the stash is still on the stack and you must remove it yourself:
# resolve the conflict, git add the file(s), then:
git stash drop
Forget that step and you will find the same stash again next week and wonder whether it contains something you're missing.
If the conflict is worse than you expected, back out:
git checkout --theirs . # or resolve properly
git reset --hard # discard the attempted restore
The stash is still there. Nothing is lost.
Cleaning Up
git stash drop stash@{1}
Removes one entry without restoring it. Use it for stashes you have identified — via git stash show — as no longer needed.
git stash clear
Deletes every stash. There is no confirmation prompt and no undo through normal commands. Run git stash list and look at what you are about to destroy first. Every time.
Turning a Stash Into a Branch
The best-kept secret in this module:
git stash branch test/fixture-rewrite-continued stash@{0}
This creates a new branch from the commit you were on when you stashed, checks it out, applies the stash there, and drops the stash if the apply succeeded.
It is the perfect answer to "this stash is a week old, the branch has moved on, and applying it produces conflicts everywhere." Restoring it onto its original starting point removes the conflicts entirely.
Pro Tip: When in doubt,
applyrather thanpop. Confirm the restore is what you expected — files present, tests behaving — and thengit stash drop. Two commands instead of one, and the stash is still there if the first one went wrong.
Key Takeaways
applyrestores and keeps;poprestores and removes;dropremoves without restoringpoprestores changes as unstaged unless you add--index- Name a specific stash with
stash@{n}, and rungit stash listfirst because indices shift - A conflicting
popdoes not drop the stash — resolve, thengit stash dropyourself git stash cleardeletes everything with no confirmation; look before you run itgit stash branch <name>recreates the original context and is the cure for an old, conflicting stash