Great work!

XP to next level

BugEater

git stash push: Putting Work in the Pocket

Learning Objectives

By the end of this lesson you will be able to:

  • Stash your changes with a message that still means something later
  • Include untracked files deliberately rather than by accident
  • Stash only some of your changes
  • Read git stash list and inspect a stash without restoring it

The Basic Command

git stash push -m "fixture rewrite, 2/3 done"
Saved working directory and index state On test/fixture-rewrite: fixture rewrite, 2/3 done

Your working directory is now clean, exactly as if you had just committed. The changes are on the stash stack.

git status
On branch test/fixture-rewrite
nothing to commit, working tree clean

You will also see the older form git stash save "message", and bare git stash with no arguments. push is the current spelling and the one that supports every option below. Bare git stash works but gives you an unnamed stash, which the next lesson will show you regretting.

Always Write a Message

Without -m, Git generates one from your last commit:

stash@{0}: WIP on test/fixture-rewrite: 8f3c2a1 Update config

That describes a commit you did not make changes to. It tells you nothing about what is in the stash.

With -m:

stash@{0}: On test/fixture-rewrite: fixture rewrite, 2/3 done — retry logic still missing

Now three days later you know whether to pop it or drop it. This costs eight seconds and it is the single most useful habit in this module.

What Gets Stashed by Default

This is the trap. By default git stash push takes:

  • ✅ Modified tracked files
  • ✅ Staged changes
  • Untracked files — brand-new files Git has never seen
  • ❌ Ignored files

So if your work-in-progress includes a new test file you have not yet run git add on, the default stash leaves it sitting in your working directory. Your tree is not actually clean, and switching branches carries that file along.

The fix:

git stash push -u -m "fixture rewrite including new helper"

-u (or --include-untracked) takes untracked files too. Use it whenever your work created new files, which for a tester writing tests is most of the time.

There is also -a (--all), which additionally stashes ignored files. That is rarely what you want — it sweeps up node_modules, build output and local .env files. Reach for -u, not -a.

Stashing Only Part of Your Work

By path, when the rest should stay in your working directory:

git stash push -m "just the config experiment" -- config/test-env.yaml

Interactively, choosing hunk by hunk:

git stash push -p

Git walks you through each change and asks whether to stash it. Useful, but slow — if you find yourself needing it often, your commits are probably too large.

Keeping the staged part in place, stashing only unstaged work:

git stash push --keep-index

The classic use is verifying a commit in isolation: stage exactly what you intend to commit, stash everything else with --keep-index, run the tests, and you have proven that this commit alone passes.

Reading the Stack

git stash list
stash@{0}: On test/fixture-rewrite: fixture rewrite, 2/3 done
stash@{1}: On main: quick check of timeout behaviour
stash@{2}: WIP on test/old-branch: 1a2b3c4 Initial smoke suite

It is a stack: stash@{0} is always the most recent, and every new stash pushes the others down. That is why stash@{1} today may be stash@{2} tomorrow — never write a stash reference in a note, write its message.

Each entry records which branch it came from, which is the detail that saves you when you find three of them.

Looking Inside Without Restoring

git stash show stash@{0}
 tests/fixtures/user.js       | 24 ++++++++++++------
 config/test-env.yaml         |  3 ++-
 2 files changed, 18 insertions(+), 9 deletions(-)

The file list — usually enough to identify a stash.

git stash show -p stash@{0}

The full diff, if you need to be sure. Neither command changes anything.

Pro Tip: Stash immediately before switching branches, not "in a minute". The gap between deciding to stash and actually stashing is where people switch branches by reflex and end up carrying half a rewrite onto a hotfix.

Key Takeaways

  • git stash push -m "message" clears your working tree and saves the changes
  • Always write a message; the generated one describes your last commit, not your work
  • The default skips untracked files — use -u when your work created new files
  • -a also sweeps ignored files and is almost never what you want
  • Stash part of your work with a path argument, -p, or --keep-index
  • git stash list shows a stack where stash@{0} is newest; git stash show [-p] inspects safely

Quiz

What does a plain git stash push leave behind in your working directory?

Which flag includes untracked files in the stash?

Why does git stash push -m "..." matter so much?

You have three stashes. Which reference always points at the most recent one?