GitSaving Changes (stash push)

Saving Changes (git stash push)

Saving a stash is how a stash session begins. The modern verb is git stash push — older docs and muscle memory use the bare git stash, which does exactly the same thing. This page covers every option you'll actually use: messages, file selection, interactive hunks, untracked/ignored files, and keeping the index intact.

The basic save

Two equivalent forms

Bash
# Classic, still works everywhere
git stash

# Modern, recommended — supports paths and more flags
git stash push
Both save tracked, modified files and anything currently staged. The working tree is reset to match `HEAD`, and the saved state becomes `stash@0`.
Always give it a message

Named stashes are findable stashes

Bash
git stash push -m "WIP on login form, validation half done"

# Later:
git stash list
# stash@{0}: On feature/login: WIP on login form, validation half done
Tip
Without `-m`, Git invents a message from the current branch and HEAD subject (e.g. `WIP on main: 3f2a1b9 Add header`). Three of those in a row are indistinguishable. Take two seconds to write a real message.
Stash only specific paths

Pathspec form — note the -- separator

Bash
# Stash just one file, leave the rest dirty
git stash push -m "experimental auth changes" -- src/auth.js

# Stash a whole directory
git stash push -m "ui rework" -- src/components/

# Stash everything except a specific path? Combine with pathspec magic:
git stash push -- ":(exclude)src/big-generated-file.ts" .

The -- separates options from pathspecs and is required whenever paths could be ambiguous. Anything after -- is treated as files.

Interactive stashing (choose hunks)

Like git add -p, but for stash

Bash
git stash push -p -m "stash only the experimental bits"
# Git walks each hunk and asks:
#   Stash this hunk [y,n,q,a,d,e,?]?
#     y - stash this hunk
#     n - do not stash this hunk
#     q - quit
#     a - stash this and all later hunks in this file
#     d - skip this and all later hunks in this file
#     e - manually edit the hunk
#     ? - help
When -p is gold
Mid-debug, you might have 40 lines of real changes plus 12 lines of `console.log` calls. `git stash push -p` lets you stash just the debug noise so you can commit the clean fix.
Including untracked files

The -u flag

Bash
# Default: untracked files are LEFT in the working tree
git stash push -m "missing scratch.txt"

# Include untracked files too
git stash push -u -m "includes new files"
# or  --include-untracked
Warning
If you stashed without `-u`, switched branches, and your new files came along, that is *normal Git behavior*. Switch back and run `git stash pop` on the original branch, then re-stash with `-u`.
Including ignored files

The -a flag (rare but exists)

Bash
git stash push -a -m "include build artifacts and node_modules"
# or  --all

-a includes everything -u does, plus files matched by .gitignore. You almost never want this — ignored files are ignored for a reason (build output, dependencies, caches). The one valid case is rescuing a one-off scratch file you forgot to un-ignore.

Keep the staging area intact

--keep-index for "test what I'm about to commit"

Bash
# Scenario: you have staged changes you want to commit, plus
# unrelated dirty work in the tree. You want to run tests against
# only the staged content.

git stash push --keep-index -m "park unrelated edits"

# Now the working tree contains exactly what is staged.
# Run your tests, commit if green:
npm test
git commit -m "Add validation"

# Bring back the parked edits
git stash pop
Why --keep-index matters
It is the cleanest way to verify that your commit on its own actually works — without your other half-finished changes helping it pass tests.
What the result looks like

A clean tree, a populated stack

Bash
git status
# On branch feature/login
# nothing to commit, working tree clean

git stash list
# stash@{0}: On feature/login: WIP on login form
# stash@{1}: On main: hotfix scratch from yesterday
Common errors

What you might see and what it means

Bash
$ git stash
No local changes to save
# Means: nothing is modified or staged. If you have new files,
# they are untracked — try  git stash -u .

$ git stash push -- nope.txt
error: pathspec 'nope.txt' did not match any file(s) known to git
# Means: the file is untracked. Either  git add  it first, or use -u
# without a pathspec.
Real-world recipe: pull --autostash

Let pull stash for you

Bash
# One-off:
git pull --autostash

# Forever:
git config --global pull.rebase true
git config --global rebase.autoStash true

With rebase.autoStash on, Git transparently stashes your dirty tree, pulls/rebases, and pops the stash back. You stop thinking about it.

Tip
Get into the habit of `git status` before every `git stash push`. It is the single best way to avoid the "wait, where did my new file go?" surprise — you'll see the `Untracked files:` section and remember to add `-u`.