Everyday Git
Topic 10

Stashing

Core

git stash shelves your uncommitted working-tree and staged changes, handing you a clean tree to switch branches or pull, then reapplies them when you ask. It solves the interrupt problem: an urgent fix needs another branch while you are mid-change and not ready to commit.

The trap is treating stash as storage rather than a short-lived holding area. Stashes are local, unnamed by default, never pushed to a remote, and easy to bury or wipe. Used for a quick context switch they are exactly right; used to park work for a week they quietly lose it.

Stashing and Restoring

git stash push records your changes and reverts the working tree to clean. To bring them back, git stash pop applies the top stash and removes it from the list, while git stash apply applies it but leaves it in the list. The difference matters when reapplying might go wrong — apply keeps a copy you can fall back on, pop assumes the apply succeeded and drops it.

The Stash Stack

Stashes form a stack: each push adds an entry on top, and they are addressed as stash@{0} (most recent), stash@{1}, and so on. git stash list shows them all. The stack is convenient for one or two entries and a liability once it grows to dozens of unlabeled WIP on... lines that no one can tell apart.

Controlling What Gets Stashed

By default stash shelves tracked changes only. New, untracked files stay in the working tree — and a later git checkout can overwrite or strand them. -u (--include-untracked) pulls those in too. --keep-index stashes the working changes but leaves the staged ones in place, useful for testing just the staged set. git stash push -p lets you stash selected hunks the same way add -p stages them.

Inspecting and Naming

A stash with no label is a mystery an hour later. git stash push -m "<what>" attaches a message so git stash list reads like notes instead of noise. To see what an entry actually contains before applying it, git stash show -p stash@{n} prints its full diff.

Branching From a Stash

If the branch has moved on since you stashed, reapplying can conflict. git stash branch <name> sidesteps that: it creates a new branch from the commit you stashed against, checks it out, and applies the stash there cleanly, then drops the stash. It is the clean recovery path when changes no longer apply to the current branch.

Common Mistakes
  • Hitting a conflict on git stash pop and assuming the stash is gone — pop does not drop the entry when the apply conflicts, so it is still in git stash list.
  • Stashing without -u, leaving new untracked files behind, then losing them to a git checkout that overwrites them.
  • Letting the stash stack grow to dozens of unlabeled WIP on... entries, making git stash list an unreadable pile.
  • Treating stash as long-term storage — entries are never pushed to a remote and are easy to lose to git stash clear or a fresh clone.
  • Running git stash pop on the wrong branch, dropping unrelated changes into a branch where they do not belong.
Best Practices
  • Label every stash with git stash push -m "<what>" so git stash list stays readable.
  • Use git stash apply instead of pop when you might need the stash again, and drop it explicitly once you confirm it applied.
  • Pass -u to include untracked files whenever your work-in-progress added new ones.
  • Use git stash branch <name> to recover changes that no longer apply cleanly instead of fighting conflicts.
  • Prefer a real WIP commit over a stash for anything you need to keep more than a day or move across machines.
Comparable toolsMercurial hg shelve / hg unshelve (shelve extension)Perforce p4 shelve / p4 unshelve, shareable with others on the serverSubversion no built-in stash; patch files or changelists as a workaroundFossil fossil stash

Knowledge Check

A git stash pop hits a conflict mid-apply. What happens to the stash entry?

  • It stays in the list — pop only drops the entry when the apply succeeds cleanly, so it is recoverable
  • It is deleted right away, since pop always removes the stash entry first, before it even attempts the apply
  • It is pushed to the configured remote as a backup the moment the conflict is detected
  • It is merged straight into the most recent commit on the branch automatically

Your work-in-progress includes a brand-new file you have not added. What does a plain git stash do with it?

  • Leaves it untracked in the working tree, where a later checkout can overwrite it — you need -u to shelve it
  • Shelves it away into the stash along with all the tracked changes by default, with no extra flag needed at all
  • Deletes it outright from the working tree, since untracked files simply cannot be stashed
  • Commits it directly to HEAD on the current branch so that it is not lost

When is git stash apply the safer choice over git stash pop?

  • When you might need the stash again — apply keeps the entry so a botched reapply still has a fallback
  • When you want the stash entry removed from the list automatically, immediately after it applies cleanly
  • When you are applying onto the exact same branch you originally stashed from
  • Never — pop is strictly the safer of the two commands in every situation

Why is stash a poor choice for work you need to keep for a week or share with a teammate?

  • Stashes are local-only, never pushed, and easily lost to git stash clear or a fresh clone — a WIP commit on a branch survives all of that
  • Stashes automatically expire after exactly seven days have passed since their creation and are then permanently deleted from the local repository
  • Stashes can hold only tracked files, so roughly half of the work-in-progress is silently missing
  • Stashes place a lock on the whole branch, which blocks the teammate from doing any work

You got correct