| |

Git 4b 🧩 Stashing Changes

⏱️ Estimated read: 11 min | |

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: pop is “apply and clean up” — the common case. apply is “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 form tells 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 branch is 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 pop removed 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

CommandPurpose
git stashSave and clear working dir
git stash push -m "msg"Save with message
git stash listList stashes
git stash popApply + remove
git stash applyApply, keep in list
git stash apply stash@{N}Apply specific
git stash drop stash@{N}Delete specific
git stash clearDelete all

Inspection

CommandShows
git stash showSummary of last stash
git stash show -pFull patch
git stash show stash@{N}Specific stash
git stash listAll stashes

Advanced

CommandPurpose
git stash branch NAMEBranch from stash
git stash push -uInclude untracked files
git stash push -aInclude ignored files
git stash push FILEStash only one file
git stash push -pInteractive stash

Pop vs Apply

Aspectpopapply
Applies✅✅
Removes from list✅❌
Reusable❌✅
Default stashMost recentMost recent

Conflict Behavior

SituationResult
Clean applyStash 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

PitfallProblemSolution
Untracked files not stashedThey stay in working dirgit stash push -u
Forgotten stashesClutterReview git stash list
Index shiftsstash@{1} becomes stash@{0}Check before using
Conflict on popStash not removedResolve, then drop
Stashing as backupNot a substitute for commitsCommit properly
Stashing across branchesApplies to current branchUse git stash branch
Losing workDropped by mistakeCheck git fsck --lost-found
Stashing half of a changeLeftover changesUse -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

CommandPurpose
git stashSave and clear
git stash push -m "msg"Save with message
git stash listList stashes
git stash popApply + remove
git stash applyApply, keep
git stash showSummary
git stash show -pFull patch
git stash dropDelete one
git stash clearDelete all
git stash branch NAMEBranch from stash

Key takeaways:

  • git stash saves uncommitted work temporarily and clears the working directory
  • It stashes both staged and unstaged changes — but not untracked files by default
  • git stash pop applies and removes; git stash apply applies but keeps
  • Stashes stack — stash@{0} is the most recent
  • Use git stash push -m "message" to make stashes identifiable
  • git stash show -p shows the full diff without applying
  • git stash branch NAME creates a branch and applies the stash cleanly when it’s stale
  • -u includes untracked files; -a includes ignored files
  • Stashes are local only — not shared, not pushed, not part of history
  • Resolve conflicts after pop and then drop the stash
  • Don’t use stash as long-term storage — commit or move to a branch
  • Clean up stashes periodically with drop or clear

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.

Was this helpful?


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!