Git 4b 🧩 Stashing Changes
git stash temporarily saves your uncommitted changes and reverts your working directory to the last commit. It’s the escape hatch for the moment you need to switch tasks but aren’t ready to commit — a half-finished feature, a file you forgot to add, a quick bug that needs attention.
Key point: A stash is a temporary shelf for work-in-progress. It saves both staged and unstaged changes, clears your working directory, and lets you come back later. It’s not a commit — it lives outside your branch history until you apply it.
Basic stash commands
The stash system has a small, clear API.
git stash — save your current uncommitted changes (staged and unstaged) and revert the working directory to the last commit.
git stash
git stash list — show all stashes, most recent first.
git stash list
Output:
stash@{0}: WIP on feature-branch: abc1234 Add login functionality
stash@{1}: On main: Fixing dashboard layout issues
git stash pop — apply the most recent stash and remove it from the list.
git stash pop
git stash apply — apply a specific stash without removing it.
git stash apply stash@{1}
You can apply the same stash multiple times. Useful when you want to test it on several branches.
git stash drop — delete a specific stash.
git stash drop stash@{0}
The stash is gone for good after this.
Why the split between pop and apply:
popis “apply and clean up” — the common case.applyis “apply but keep it around” — useful when you’re not sure the stash belongs on this branch yet.
Practical examples
Three common scenarios.
Example 1: Switching branches temporarily
You’re deep in a feature branch and need to check something on main, but you have half-finished work.
$ git status
On branch feature-branch
Changes to be committed:
modified: src/login.js
Changes not staged for commit:
modified: src/dashboard.js
$ git stash
Saved working directory and index state WIP on feature-branch: abc1234 Add login functionality
$ git checkout main
Switched to branch 'main'
$ git checkout -b hotfix/urgent-bug
Switched to a new branch 'hotfix/urgent-bug'
Work on the hotfix. When done, come back:
$ git checkout feature-branch
Switched to branch 'feature-branch'
$ git stash pop
On branch feature-branch
Changes to be committed:
modified: src/login.js
Changes not staged for commit:
modified: src/dashboard.js
Your work is back — exactly as you left it.
Why this is the classic use case: You need to act on something else but can’t commit half-finished work. Stash saves it, clears the way, and restores it later.
Example 2: Managing multiple tasks
You’re working on a feature when something urgent needs testing.
$ git stash
Saved working directory and index state WIP on develop: def5678 Implement user profile
Quick test changes:
$ git add test.js
$ git commit -m "Quick test changes"
$ git push origin develop
Switch back:
$ git stash pop
On branch develop
Changes to be committed:
modified: src/user-profile.js
Your original work is restored.
Why this pattern matters: Stashing separates “the thing I was working on” from “the thing that just came up.” You don’t lose your place, and you don’t leave half-done work committed.
Example 3: Multiple stashes
When you have more than one thread of work-in-progress.
$ git stash save "Working on login form"
Saved working directory and index state WIP on develop: def5678 Implement user profile
# make more changes
$ git stash save "Fixing dashboard layout issues"
Saved working directory and index state WIP on develop: def5678 Implement user profile
List them:
$ git stash list
stash@{0}: On develop: Fixing dashboard layout issues
stash@{1}: On develop: Working on login form
Apply a specific one:
$ git stash apply stash@{1}
Drop one you no longer need:
$ git stash drop stash@{0}
Dropped stash@{0} (34a2b5c...)
Stashes are referenced by index, with stash@{0} being the most recent.
Why messages matter:
stash@{1}isn’t descriptive.stash@{1}: Working on login formtells you what’s inside. Always save with a message when you have more than one.
Advanced stash commands
git stash save "message" — save with a descriptive message.
git stash save "Fixing authentication bug"
The message shows up in git stash list. Newer Git prefers git stash push -m "message", but save still works.
git stash show — show what changed in the most recent stash.
git stash show
Summary output — file names and change counts.
git stash show -p — show the full patch.
git stash show -p
Full diff, like git show but for the stash.
git stash branch NAME — create a new branch from a stash and apply it.
git stash branch new-feature-stash
This checks out a new branch at the commit the stash was based on, then applies the stash. Useful when the stash has become stale and would conflict on the current branch.
Why
git stash branchis underused: If a stash conflicts badly when applied, this is the cleanest fix. Git rewinds to the base commit, creates a branch, and applies cleanly.
Stash with conflicts
Stashes can conflict just like merges.
$ git stash pop
Auto-merging src/dashboard.js
CONFLICT (content): Merge conflict in src/dashboard.js
The stash change could not be applied.
The stash stays in the list — pop doesn’t remove it when there’s a conflict. Resolve the conflict markers manually, stage the file, and drop the stash when you’re done.
# resolve the conflict in the editor
git add src/dashboard.js
git stash drop
Why the stash sticks around: If
popremoved the stash on conflict, you’d lose the ability to retry. Keeping it in the list means you can reattempt after fixing the working directory.
Complete Example Session
# ============================================
# PART 1: BASIC STASH
# ============================================
# Make some changes
echo "new line" >> file1.js
echo "another line" >> file2.js
git status
# [ modified: file1.js ]
# [ modified: file2.js ]
git stash
# [ Saved working directory and index state WIP on main: abc1234 ]
git status
# [ nothing to commit, working tree clean ]
# ============================================
# PART 2: LIST STASHES
# ============================================
git stash list
# [ stash@{0}: WIP on main: abc1234 ]
# ============================================
# PART 3: POP
# ============================================
git stash pop
# [ On branch main ]
# [ Changes not staged for commit: ]
# [ modified: file1.js ]
# [ modified: file2.js ]
# [ Dropped refs/stash@{0} ]
git stash list
# (empty)
# ============================================
# PART 4: APPLY INSTEAD OF POP
# ============================================
git stash push -m "Work in progress"
git stash apply
# (changes reapplied)
git stash list
# [ stash@{0}: On main: Work in progress ]
# (still there)
# ============================================
# PART 5: MULTIPLE STASHES
# ============================================
echo "change A" >> a.js
git stash push -m "Stash A"
echo "change B" >> b.js
git stash push -m "Stash B"
git stash list
# [ stash@{0}: On main: Stash B ]
# [ stash@{1}: On main: Stash A ]
# ============================================
# PART 6: APPLY A SPECIFIC STASH
# ============================================
git stash apply stash@{1}
# Applies Stash A
# ============================================
# PART 7: SHOW WHAT'S IN A STASH
# ============================================
git stash show
# [ a.js | 1 + ]
# [ 1 file changed, 1 insertion(+) ]
git stash show -p
# [ diff --git a/a.js b/a.js ]
# [ index abc1234..def5678 100644 ]
# [ --- a/a.js ]
# [ +++ b/a.js ]
# [ @@ -0,0 +1 @@ ]
# [ +change A ]
# ============================================
# PART 8: DROP A STASH
# ============================================
git stash drop stash@{0}
# [ Dropped stash@{0} (34a2b5c...) ]
git stash list
# [ stash@{0}: On main: Stash A ]
# ============================================
# PART 9: STASH BRANCH
# ============================================
git stash push -m "Half-finished feature"
git stash branch feature/from-stash
# [ Switched to a new branch 'feature/from-stash' ]
# [ On branch feature/from-stash ]
# [ Changes not staged for commit: ]
# [ modified: file1.js ]
# [ Dropped refs/stash@{0} ]
Quick Reference
Core Commands
| Command | Purpose |
|---|---|
git stash | Save and clear working dir |
git stash push -m "msg" | Save with message |
git stash list | List stashes |
git stash pop | Apply + remove |
git stash apply | Apply, keep in list |
git stash apply stash@{N} | Apply specific |
git stash drop stash@{N} | Delete specific |
git stash clear | Delete all |
Inspection
| Command | Shows |
|---|---|
git stash show | Summary of last stash |
git stash show -p | Full patch |
git stash show stash@{N} | Specific stash |
git stash list | All stashes |
Advanced
| Command | Purpose |
|---|---|
git stash branch NAME | Branch from stash |
git stash push -u | Include untracked files |
git stash push -a | Include ignored files |
git stash push FILE | Stash only one file |
git stash push -p | Interactive stash |
Pop vs Apply
| Aspect | pop | apply |
|---|---|---|
| Applies | ✅ | ✅ |
| Removes from list | ✅ | ❌ |
| Reusable | ❌ | ✅ |
| Default stash | Most recent | Most recent |
Conflict Behavior
| Situation | Result |
|---|---|
| Clean apply | Stash removed (pop) |
| Conflict (pop) | Stash kept in list |
| Conflict (apply) | Stash kept (always) |
Best Practices
✅ Do This:
# Use descriptive messages
git stash push -m "Fix login validation" # ✅
# List stashes to see what's there
git stash list # ✅
# Use pop when you're applying and done
git stash pop # ✅
# Use apply when you're testing
git stash apply stash@{1} # ✅
# Show what's in a stash before applying
git stash show -p stash@{0} # ✅
# Drop stashes you no longer need
git stash drop stash@{0} # ✅
# Use stash branch when a stash is stale
git stash branch feature/from-stash # ✅
❌ Don’t Do This:
# Don't accumulate unnamed stashes
git stash # ⚠️ hard to identify later
# Don't forget a stash exists
# Check the list occasionally # ⚠️
# Don't stash long-term work
# Commit or move to a branch instead # ⚠️
# Don't use stash for sharing
# It's local-only # ❌
# Don't pop a stash that conflicts
# Resolve first, then drop # ⚠️
# Don't stash untracked files by accident
# They're not included by default # ⚠️
# Don't rely on stash index numbers
# They shift as stashes are added/dropped # ⚠️
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Untracked files not stashed | They stay in working dir | git stash push -u |
| Forgotten stashes | Clutter | Review git stash list |
| Index shifts | stash@{1} becomes stash@{0} | Check before using |
| Conflict on pop | Stash not removed | Resolve, then drop |
| Stashing as backup | Not a substitute for commits | Commit properly |
| Stashing across branches | Applies to current branch | Use git stash branch |
| Losing work | Dropped by mistake | Check git fsck --lost-found |
| Stashing half of a change | Leftover changes | Use -p for interactivity |
Real-World Examples
1. Stash and switch
git stash
git checkout main
Common branch-switch pattern.
2. Stash with message
git stash push -m "Half-done login form"
Easier to find later.
3. List stashes
git stash list
Shows all saved stashes.
4. Apply specific stash
git stash apply stash@{2}
Applies without removing.
5. Pop the latest
git stash pop
Applies and removes.
6. Drop a stash
git stash drop stash@{0}
Deletes it.
7. Clear all
git stash clear
Removes every stash.
8. Show patch
git stash show -p
Full diff of the latest stash.
9. Include untracked
git stash push -u
Also stashes untracked files.
10. Include ignored
git stash push -a
Includes ignored files too.
11. Stash one file
git stash push file.js
Only that file is stashed.
12. Stash with interactivity
git stash push -p
Choose which hunks to stash.
13. Branch from stash
git stash branch feature/from-stash
Creates a branch and applies the stash.
14. Resolve conflicts after pop
git stash pop
# conflict
# resolve file
git add file.js
git stash drop
Clean up after resolving.
15. Check what changed
git stash show
Summary of the last stash.
Visual: Stash Lifecycle
┌──────────────────────────────────────────────┐
│ Working directory has changes │
│ │
│ git stash │
│ │ │
│ ▼ │
│ Changes moved to stash stack │
│ Working directory is clean │
│ │
│ │ │
│ ▼ │
│ git stash list │
│ stash@{0}: latest │
│ stash@{1}: next │
│ ... │
│ │
│ │ │
│ ▼ │
│ git stash pop │
│ → apply changes to working directory │
│ → remove from stack │
│ │
│ git stash apply │
│ → apply changes │
│ → keep in stack │
│ │
└──────────────────────────────────────────────┘
Visual: Stash Stack
┌──────────────────────────────────────────────┐
│ stash@{0} ← most recent │
│ stash@{1} │
│ stash@{2} │
│ stash@{3} ← oldest │
│ │
│ New stashes push on top │
│ pop/apply uses the most recent by default │
│ drop removes a specific one │
│ │
└──────────────────────────────────────────────┘
Visual: Pop vs Apply
┌──────────────────────────────────────────────┐
│ git stash pop │
│ │
│ Apply + remove │
│ │
│ stash@{0} ──► working dir │
│ stash@{0} deleted │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ git stash apply │
│ │
│ Apply only │
│ │
│ stash@{0} ──► working dir │
│ stash@{0} still in list │
│ │
│ Can apply again to another branch │
│ │
└──────────────────────────────────────────────┘
Visual: Common Workflow
┌──────────────────────────────────────────────┐
│ Working on feature │
│ │ │
│ ▼ │
│ Urgent interruption │
│ │ │
│ ▼ │
│ git stash push -m "Half-done feature" │
│ │ │
│ ▼ │
│ Switch to main, fix urgent issue │
│ │ │
│ ▼ │
│ Switch back to feature │
│ │ │
│ ▼ │
│ git stash pop │
│ │ │
│ ▼ │
│ Continue where you left off │
│ │
└──────────────────────────────────────────────┘
Visual: Stash Branch
┌──────────────────────────────────────────────┐
│ Stash from main │
│ │ │
│ ▼ │
│ main has moved on │
│ │ │
│ ▼ │
│ git stash apply → conflicts │
│ │
│ Better: │
│ git stash branch feature/from-stash │
│ │ │
│ ▼ │
│ Branch created at stash base │
│ Stash applied cleanly │
│ │
└──────────────────────────────────────────────┘
Summary
| Command | Purpose |
|---|---|
git stash | Save and clear |
git stash push -m "msg" | Save with message |
git stash list | List stashes |
git stash pop | Apply + remove |
git stash apply | Apply, keep |
git stash show | Summary |
git stash show -p | Full patch |
git stash drop | Delete one |
git stash clear | Delete all |
git stash branch NAME | Branch from stash |
Key takeaways:
git stashsaves uncommitted work temporarily and clears the working directory- It stashes both staged and unstaged changes — but not untracked files by default
git stash popapplies and removes;git stash applyapplies but keeps- Stashes stack —
stash@{0}is the most recent - Use
git stash push -m "message"to make stashes identifiable git stash show -pshows the full diff without applyinggit stash branch NAMEcreates a branch and applies the stash cleanly when it’s stale-uincludes untracked files;-aincludes ignored files- Stashes are local only — not shared, not pushed, not part of history
- Resolve conflicts after
popand thendropthe stash - Don’t use stash as long-term storage — commit or move to a branch
- Clean up stashes periodically with
droporclear
Remember: Stash is the escape hatch for “I need to switch tasks but I’m not ready to commit.” It saves work, clears the way, and restores it later. Use messages, review the list, prefer pop when done and apply when testing. And don’t let stashes pile up — commit them properly when the work deserves it.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!