In real projects, the “urgent hotfix” arrives exactly when you’re mid-feature with half-written code and tests open. You need a clean branch immediately, but you don’t want to toss your work or make a noisy WIP commit. That’s where git stash shines: it takes a snapshot of your working tree and (optionally) your staging area (index), parks it safely, and resets your tree to HEAD so you can switch context without risk.

Below I guide you through the exact flows I use on team projects: cleanly pausing work, jumping to hotfixes, restoring the exact state (including what was staged), moving a stash into its own branch, and a few creative tricks that make stash feel like a superpower. I’ll show the classic commands (as they appeared in my terminal) and note the modern equivalents that read better and help teammates.

Reference while you read: the official docs are excellent and precise — keep them open: git-scm.com/docs/git-stash.

1) A Clear Mental Model

A stash is a pair of snapshots:

By default, stash captures tracked files. Add -u/--include-untracked to include new, untracked files (and --all if you also want ignored files). Stashes live in a local stack: newest is stash@{0}, then stash@{1}, and so on. They’re local — not pushed to remotes — and that’s intentional.

Modern tip: git stash push -m "message" is the current, explicit form. Calling just git stash still works (and is equivalent to stash push), but I prefer push -m for clarity in teams.

2) Parking Work to Ship a Hotfix (The Everyday Case)

Situation: On main, I’ve edited blog.html. Pager goes off. We need a hotfix.

What I did (classic):

git status
# shows modified: blog.html
git stash
# Saved working directory and index state WIP on main: <…>
git stash list
# stash@{0}: WIP on main: <…> (newest on top)

Why: Stashing gives me a clean working tree so I can branch for the hotfix without dragging along my WIP.

Modern equivalent:

git stash push -m "WIP: blog.html edits on main"

Now I branch, fix, and commit the hotfix:

Classic:

git checkout -b hotfix
git commit -am "hotfix: updated hello world - hello_world.py"

Modern:

git switch -c hotfix
# …fix…
git commit -am "hotfix: updated hello world - hello_world.py"

Back on main, I had a quick tweak to 404.html. I stashed it with a message (this matters once you have multiple stashes):

Classic:

git stash save "modified the title - 404.html"
git stash list
# stash@{0}: On main: modified the title - 404.html
# stash@{1}: WIP on main: <…>

Modern:

git stash push -m "modified the title - 404.html"

Team reality: When multiple engineers are hopping branches, labeled stashes act like a to-do stack you can understand at a glance.

3) “What’s Inside This Stash?” (Choosing the Right One)

Sometimes I need to inspect an older, unlabeled stash to see what it changes:

git stash show stash@{2}
# blog.html | 2 +-
# 1 file changed, 1 insertion(+), 1 deletion(-)

Add -p to view the patch:

git stash show -p stash@{2}

Why: I don’t want to apply/pop a random stash and create conflicts; I want the right one, first time.

4) Untracked Files: Why “No local changes to save” Happens

You’ll hit this sooner than you think. I added a brand-new newfile.txt, then:

git stash
# No local changes to save

Because it’s untracked, plain stash ignored it. The fix:

Classic:

git stash -u

Modern:

git stash push -u -m "Include untracked: newfile.txt"
# or include ignored too:
git stash push --all -m "Include untracked+ignored"

Team scenario: Spikes, throwaway scripts, notes — they’re often untracked. If you want to park them, remember -u (or --all).

5) Apply vs Pop vs Drop (Restoring Intentionally)

I typically apply when I might reuse the stash and pop when I’m done with it:

git stash apply           # restore, but keep in the stack
git stash pop stash@{1} # restore and remove that entry if apply succeeds
git stash drop stash@{2} # remove a specific entry unconditionally
git stash clear # blow away all stashes (irreversible)
Conflict note: If apply/pop hits conflicts, Git leaves the stash in place. Resolve files, stage (git add), then drop or pop again as needed.

Team scenario: After a hotfix merges, I apply the relevant stash back on main, finalize the change, and drop the stash so the stack doesn’t grow stale.

6) Exact Restoration: Don’t Lose Your Staging Plan

This is the most common gotcha. Say I had newfile.txt staged and newfile2.txt unstaged, then I stashed. A plain apply brings everything back unstaged, which is not what I want when I’m composing clean, small commits.

Use --index to restore the index snapshot too:

git stash apply --index
# or
git stash pop --index

Why: A stash stores two trees (index + working). --index restores both. In team reviews, this helps you keep tight commit boundaries you planned before the interruption.

7) Keep Staged, Stash Only the Rest (--keep-index)

Sometimes I want to keep my staged changes ready for an immediate commit and hide only the other, noisy edits:

Classic:

git stash --keep-index

Modern:

git stash push --keep-index -m "Stash only unstaged; keep staged intact"

Team scenario: You’re splitting work into multiple logical commits; stash the unfinished hunks and ship the one that’s ready.

Bonus precision:

git stash push -- path/to/fileA dirB/          # stash only these paths
git stash push -p -m "Interactive patch stash" # pick specific hunks
git stash push --staged -m "Only staged changes to stash

8) When a Stash Deserves Its Own Branch

Large stashes are harder to reason about and review. I convert them into a branch:

git stash branch demobranch           # uses latest stash by default
# or explicitly:
git stash branch demobranch stash@{0}

This does four things for you:

  1. creates the branch at the commit where the stash was made,
  2. checks it out,
  3. applies the stash (so you see your changes as edits),
  4. drops that stash entry on success.

From there, I commit normally, open a PR, run CI, get reviews — in short, I make the work first-class history instead of a blob hidden in my stash stack.

Team scenario: If apply keeps conflicting on main because the base moved, stash branch applies on the original base — far fewer conflicts.

9) File Undo: Prefer restore Over Legacy checkout --

You’ll see old docs (and muscle memory) using git checkout -- <path> to discard a file. The intent is clearer with:

git restore <path>          # discard working changes to that file
git restore --staged <path> # unstage but keep edits

I’ve found teammates new to Git make fewer mistakes when we standardize on switch (for branches) and restore (for files).

10) Putting It Together: A Smooth, Team-Friendly Flow

Here’s a tidy day-in-the-life using modern forms:

# On main, mid-feature:
git status
git stash push -m "WIP: blog.html edits"
git switch -c hotfix
# ... fix, run tests ...
git commit -am "hotfix: correct 500 message"
git switch main
git stash push -m "WIP: 404 title tweak" # label each stash
# Include a new untracked scratch file
git stash push -u -m "Spike: newfile.txt"
# Later: restore EXACT staged/unstaged state
git stash apply --index
# Decide this belongs on its own branch:
git stash branch demobranch stash@{1}
# ... commit in small pieces, open PR, get review ...

This sequence plays nicely with CI, code review, and release trains — the things that truly matter on a team.

11) Why I Reach for Stash (and When I Don’t)

I avoid using stash as a long-term drawer. It’s local, easy to forget, and invisible to your teammates. If it’s important, promote it to a branch and make proper commits.

12) Quick Command Map (Classic → Modern)

13) Final Notes & Doc Link

git stash isn’t just a panic button. Used deliberately — with messages, --index, --keep-index, -u, and stash branch — it keeps your flow intact and your team’s history clean. Keep the official documentation close (it covers advanced switches like --patch, --staged, export/import, and configuration toggles): Official docs: git-scm.com/docs/git-stash.

If you adopt the modern forms (stash push, switch, restore) and the habits above, you’ll move between urgent tasks and deep work without losing a minute — or a single carefully staged hunk.