Git Stash: How I Stopped Losing Work Mid-Feature (And You Can Too)

Git Stash: How I Stopped Losing Work Mid-Feature (And You Can Too)

I’ll be honest — the first time I discovered git stash, it felt like finding a secret room in a house I’d been living in for years.

I had been hacking on a new API integration for about three hours when Slack lit up: production was throwing 500 errors on the payment endpoint. Classic. I panicked, ran git status, saw 30-odd modified files, and had no clean way out. I didn’t want to commit half-baked code. I didn’t want to throw away three hours of work. I ended up copying my changes to a text file like an animal.

Then I learned about git stash. Never again.

Here’s everything I know about it — including the gotchas that bit me.


What Git Stash Actually Does

git stash snapshots your current working directory — both staged and unstaged changes — and saves that snapshot to a local stack. Your working directory goes back to a clean state (matching the last commit), and you can restore the snapshot whenever you’re ready.

Think of it as a clipboard that survives branch switching.

Working directory (messy)
        ↓ git stash
Clean working directory  +  stash stack → [ stash@{0}, stash@{1}, ... ]
        ↓ git stash pop
Working directory (messy again, where you left off)

Crucially: stashes are local only. They don’t get pushed to a remote. They live on your machine, tied to your local Git repo.


When to Reach for Stash

Situation What stash buys you
Urgent hotfix while mid-feature Switch branches cleanly, no half-baked commit
Realized you’re on the wrong branch Move changes over without losing anything
Need a clean git pull Avoid the “please commit or stash” error
Want to test something with a clean slate Temporarily set aside WIP and test the baseline
Apply the same small fix to multiple branches Stash once, apply many times

The Commands You’ll Actually Use

Saving a Stash

# Quickest — but gives you a useless name like "WIP on feature/login"
git stash

# Always do this instead — label it
git stash save "WIP: refactor auth middleware, step 2 of 4"

# New syntax (Git 2.13+), same result, supports more options
git stash push -m "WIP: refactor auth middleware, step 2 of 4"

# Stash untracked (new) files too
git stash -u

# Stash untracked AND ignored files (rarely needed)
git stash -a

# Stash only a specific file
git stash push -m "tweak: header padding only" src/components/Header.css

Real talk: I used to never add messages. After accumulating stash@{0} through stash@{7} with names like “WIP on main” and forgetting what any of them contained, I started treating stash messages the same as commit messages. Do it from day one.


Checking What You’ve Stashed

# See everything in the stash stack
git stash list

Sample output:

stash@{0}: On feature/checkout: WIP: cart total calculation, edge cases pending
stash@{1}: On main: hotfix: null check before payment gateway call
stash@{2}: On develop: WIP: API integration — auth token refresh not working yet

The index starts at {0} for the most recent stash. Once a stash is popped or dropped, everything shifts up.

# Quick summary: which files changed
git stash show

# Full diff — see exactly what's in there
git stash show -p

# Inspect a specific stash
git stash show -p stash@{2}

I run git stash show -p stash@{N} before restoring anything I haven’t touched in a few days. Context evaporates fast.


Restoring Stashed Work

# Pop: restore AND remove from the stash stack (most common)
git stash pop

# Apply: restore but LEAVE it in the stash stack (safer)
git stash apply

# Target a specific stash
git stash pop stash@{1}
git stash apply stash@{2}

My rule: if there’s any chance the restore might conflict, I use apply first. If everything merges cleanly and I’m satisfied, then I drop it manually. Losing a stash to an accidental pop with conflicts is painful.


Cleaning Up Stashes

# Drop one specific stash
git stash drop stash@{0}

# Drop EVERYTHING in the stash stack — no confirmation prompt
git stash clear

⚠️ git stash clear is irreversible. There’s no git stash clear --undo. Once it’s gone, it’s gone.


Advanced Moves

Create a Branch Directly from a Stash

git stash branch feature/auth-refactor stash@{0}

This one command: 1. Creates a new branch off the commit where the stash was made 2. Checks it out 3. Applies the stash 4. Drops the stash if apply succeeded

I use this when I stashed changes days ago and the branch I stashed from has moved on significantly. Applying directly would be a conflict minefield — branching from the stash’s origin point sidesteps the problem entirely.

Stash Everything Except What’s Already Staged

git stash --keep-index

Useful when you’ve carefully staged a clean subset of changes and want to stash the rest (your WIP noise) before committing. This way you can commit just the staged chunk without the unfinished stuff cluttering your diff.

Interactive Partial Stash

git stash push -p

This drops you into an interactive hunk selector — the same interface as git add -p — so you can choose exactly which hunks to stash. Granular, but slow. Worth knowing when you need surgical precision.


Real Workflows From My Own Projects

Scenario 1: The Production Fire Drill

Classic. Deep in a feature, Slack goes red.

# Save exactly where I am
git stash save "WIP: checkout flow — promo code validation incomplete"

# Switch to main and branch off for the fix
git checkout main
git pull origin main
git checkout -b hotfix/payment-500-error

# ... diagnose, fix, commit, open PR ...

# After the hotfix is merged, return to the feature
git checkout feature/checkout-flow
git stash pop

The whole handoff takes under 30 seconds. No half-baked commits cluttering history, no lost work.


Scenario 2: Wrong Branch (It Happens to Everyone)

You’ve been coding for 45 minutes and realize you’re on main.

# Lock in the work
git stash save "oops: started new feature on main — moving to correct branch"

# Go where you should have been
git checkout -b feature/user-onboarding

# Bring the work over
git stash pop

Scenario 3: Pull Without the “Please Commit or Stash” Error

git stash save "WIP: pre-pull stash"
git pull origin main
git stash pop
# Resolve merge conflicts here if any

Note: if git stash pop after a pull creates conflicts, Git will flag them in the files as usual. The stash won’t be dropped (see troubleshooting below).


Scenario 4: Apply the Same Change to Multiple Branches

I recently fixed a misconfigured timeout value that needed to land on both develop and staging:

git stash save "fix: API timeout set to 10s (was 3s)"

# Apply to develop — use apply, not pop, so we keep the stash
git checkout develop
git stash apply
git add config/api.js
git commit -m "fix: API timeout set to 10s"

# Apply to staging — pop to clean up at the end
git checkout staging
git stash pop
git add config/api.js
git commit -m "fix: API timeout set to 10s"

Troubleshooting: What to Do When Things Go Sideways

Problem: git stash pop caused merge conflicts — now what?

When git stash pop hits conflicts, Git applies what it can and marks the conflicting hunks. The stash entry is NOT deleted — it stays in the stack until you explicitly drop it.

# 1. See what conflicted
git status

# 2. Resolve conflicts in each file (open in your editor)
# Look for <<<<<<< / ======= / >>>>>>> markers

# 3. Stage the resolved files
git add src/conflicted-file.js

# 4. Manually drop the stash (it wasn't auto-removed)
git stash drop

Do NOT run git stash pop again. The stash is still there — you’ll double-apply it.


Problem: Stashed changes disappeared after git stash clear

They’re gone. git stash clear has no undo.

Prevention: before clearing, always check what you’re deleting:

git stash list
git stash show -p stash@{0}  # inspect before nuking
git stash clear

If you accidentally cleared and need to recover, it’s sometimes possible via git fsck:

git fsck --unreachable | grep commit | awk '{print $3}' | xargs git log --merges --no-walk

This surfaces dangling commits that might include your stash objects. Not guaranteed to work, especially after garbage collection. Don’t rely on this — just be careful with clear.


Problem: New files aren’t included in the stash

By default, git stash ignores untracked files (new files not yet added with git add).

# Wrong — new files won't be stashed
git stash

# Right — includes untracked files
git stash -u

I got burned by this when I stashed a branch with several new components, switched contexts, came back, ran git stash pop, and was confused why my new files were gone. They were never stashed. Always use -u when you have new files.


Problem: git stash pop restored changes to the wrong branch

Stashes are branch-agnostic — git stash pop applies to whatever branch you’re currently on. Git will warn you if the stash was created on a different branch, but it won’t stop you.

# Before popping, double-check your current branch
git branch --show-current

# Then pop
git stash pop

If you popped on the wrong branch, you can stash it again and move it.


Problem: Stash stack has grown out of control

git stash list

If you see more than 4–5 entries, it’s time to audit. For each one:

git stash show -p stash@{N}

Either apply and commit, or drop. Stashes are not a long-term storage solution — that’s what branches and commits are for.


Caveats and Limits to Know

  • Stashes are local. git push doesn’t push them. git clone doesn’t copy them. They live only on the machine where they were created.
  • Stash vs. WIP commit: for longer-lived “saves,” consider a WIP commit on a personal branch instead. You can always git reset HEAD~1 to un-commit it later. WIP commits survive machine changes and collaborators pulling your branch.
  • git stash clear is destructive and immediate. No confirmation. No undo (usually). Treat it like rm -rf.
  • Conflicts on pop are normal, not a bug. If your branch moved on since you stashed, expect conflicts. Plan for resolution time.
  • Stash doesn’t save your Git index state perfectly. In some edge cases with --keep-index or partial stashes, what you get back might not be staged exactly as before. Always git status after restoring.

Quick Reference

Command What it does
git stash save "msg" Save with a label
git stash push -m "msg" <file> Stash a specific file
git stash -u Include untracked files
git stash list Show the full stash stack
git stash show -p stash@{N} Full diff of a stash
git stash pop Restore latest, delete from stack
git stash apply stash@{N} Restore specific, keep in stack
git stash drop stash@{N} Delete one stash
git stash clear Delete ALL stashes (no undo)
git stash branch <name> stash@{N} Create branch from stash
git stash push -p Interactive partial stash
git stash --keep-index Stash unstaged, keep staged

Final Thoughts

git stash is one of those commands that slots quietly into your muscle memory and then one day saves your entire afternoon. The basics — save, pop, list — cover 90% of real-world situations. The advanced options — branch, --keep-index, -p — are there when you need surgical precision.

The two habits that made the biggest difference for me:

  1. Always write a message. Nameless stashes are a trap you set for your future self.
  2. Audit regularly. If your stash list is longer than 3 entries, something is being avoided, not solved. Commit it, branch it, or drop it.

If you’re interested in other Git workflows that save time on real projects — like interactive rebasing or bisect for hunting bugs — those are coming up next on Private Labs.


More in Problem Solving.

Leave a Reply

Your email address will not be published. Required fields are marked *.

*
*