git stash push -- path/to/file stashes that one file and leaves everything else in your working tree. The -- matters: it tells Git the argument is a path and not a branch name, which is the difference between a stash and a confusing error.
This gets searched constantly because the obvious guess does not work. git stash file.js looks like it should stash a file, and it does not — for a long time Git rejected it outright, and stash’s pathspec support was added late enough that plenty of tutorials still predate it. Once you know the flag, the operation is trivial. The more interesting question is whether stashing was the right tool for what you were doing.
Table of contents
- The command
- Stashing part of a file
- The inverse: everything except one file
- Restoring one file out of a stash
- When a branch is the better answer
- Common failure modes
- How this fits the rest of the stack
- FAQ
The command
git stash push -- src/config.js
git stash push -m "wip config" -- src/config.js
git stash push -- src/config.js src/utils.js
git stash push -- 'src/**/*.test.js'
push is the modern spelling of what used to be git stash save. Save still works and is deprecated; it also cannot take a pathspec, which is exactly why the old advice on this topic says it is impossible.
Always pass -m with something descriptive. A stash list of six entries all reading WIP on main: 3f2a1b0 fix tests is useless, and you will not remember which is which by tomorrow. Thirty characters of context costs nothing and saves the guessing.
By default git stash ignores untracked files. If the file you want to stash is new, add -u:
git stash push -u -- src/newfile.js
This is a common five minutes of confusion — you stash, the new file is still sitting there, and you assume the pathspec failed. It did not; Git simply does not consider untracked files part of the working state unless you ask it to.
Stashing part of a file
Sometimes the unit is smaller than a file. You have a debugging console.log sitting three lines from a real fix and you want to keep one and park the other.
git stash push -p
git stash push -p -- src/config.js
-p walks you through each hunk and asks. The prompt keys that matter: y stash this hunk, n keep it, s split it into smaller hunks, e edit the diff by hand, q stop. s is the one that does most of the work when two unrelated changes end up adjacent.
Combining -p with a pathspec narrows the walk to one file, which saves paging through everything else to reach the hunk you care about.
Interactive staging is a skill worth having generally. The same -p flag works on git add, git checkout, git restore, and git reset, with the same key bindings. Learning it once pays off across all of them.
The inverse: everything except one file
Often the real goal is stash all my noise but leave this one thing alone. Pathspec magic handles it, though the syntax is not obvious.
git stash push -- ':!src/config.js'
git stash push -- . ':!src/config.js' ':!*.md'
The :! prefix is a negative pathspec. Quote it, because ! triggers history expansion in bash and produces a baffling error if left bare.
The alternative that people find easier to reason about: stage what you want to keep, stash the rest with --keep-index.
git add src/config.js
git stash push --keep-index
This is genuinely useful for testing. Stage the change you think fixes the bug, stash everything else, run the test suite against a tree containing only that change. If it passes, you have proven the fix in isolation rather than in a tree full of other edits.
Restoring one file out of a stash
The reverse operation. You have a stash with six files in it and you want one of them back without applying the whole thing.
git checkout stash@{0} -- src/config.js
# modern equivalent
git restore --source=stash@{0} -- src/config.js
# see what is in a stash first
git stash show -p stash@{0}
git stash show --name-only stash@{0}
Two things to know about this. First, it overwrites your working copy of that file with no confirmation and no merge — if you have uncommitted changes there, they are gone. Commit or stash them first.
Second, this does not remove the file from the stash. The stash entry stays intact with all six files. That is usually what you want, but it means you have to git stash drop yourself once you are finished, and stashes that nobody drops accumulate for months.
git stash show --name-only before doing anything is a cheap habit. Ten seconds of looking beats applying the wrong stash and untangling it.
When a branch is the better answer
Here is the opinion. Stash is a good tool for the next ten minutes and a bad one for the next ten days. It is an unnamed, unpushed, ordinal-indexed pile that lives only on your machine, is invisible to everyone else, and is not backed up by anything.
Every serious loss-of-work story involving stash follows the same shape: git stash before a rebase, the rebase goes badly, git reset --hard to recover, git stash pop produces a conflict, and somewhere in the panic the entry gets dropped. Reflog can sometimes get it back. Sometimes.
A scratch commit on a scratch branch costs one extra command and fixes all of it:
git switch -c wip/config-experiment
git add src/config.js
git commit -m "wip: config experiment"
git switch -
Now it has a name, it survives everything, you can push it, and a colleague can look at it. When you come back, git cherry-pick or a soft reset brings it forward. The only real cost is a branch you have to delete later, which is a much smaller problem than a stash you cannot find.
Use stash for what it is genuinely good at: I need to check out main for two minutes to reproduce something. Anything with a longer half-life than lunch belongs on a branch.
Common failure modes
- Pathspec did not match any file. The path is relative to the repository root, not your current directory. Run
git statusand copy the path from there. - New file did not get stashed. It is untracked. Use
-u. - Conflict on pop. The tree moved under the stash. Resolve as a normal merge conflict, then
git stash drop— a conflictingpopdoes not drop the entry automatically, which is deliberate and means you get a second chance. - Dropped the wrong stash.
git fsck --unreachable | grep commitcan surface the dangling commit, andgit stash apply <sha>can bring it back. This works more often than people expect and is worth trying before giving up. - Stash list has grown to twenty entries. Not a failure exactly, but a signal.
git stash listonce a week and clear the ones you cannot identify.
How this fits the rest of the stack
Half of what stash is used for is really a shortage of cheap, safe places to try something. Branches solve that locally; a deploy that can be rolled back solves it in production. When a change looks fine locally and behaves badly live, having the previous deploy sitting one action away turns a stressful evening into a routine one — and the build log for both deploys is right there to compare. Deploying from GitHub on RunxBuild covers how pushes become deploys and what gets recorded along the way. When you are working out what a preview or staging environment would cost alongside production, the RunxBuild hosting calculator lists the service, database, and bandwidth separately so a second environment is a number you can look at rather than guess at.
Useful related references:
- How to Rename a File in Linux: mv, rename, and git mv
- Revert a Single File in Git: Restoring One Path Without Touching the Rest
- git push -f: When It Is Fine, When It Is Not, and the Safer Flag
- Services on RunxBuild
FAQ
How do I stash a single file in Git?
Run git stash push -- path/to/file. The double dash tells Git the argument is a path rather than a branch name. Add -m "message" to label the stash, and -u if the file is untracked, since stash ignores untracked files by default.
Why does git stash save with a filename not work?
git stash save never supported pathspecs and is now deprecated. Pathspec support was added to git stash push, which is the modern form. Use git stash push -- file instead.
How do I stash everything except one file?
Use a negative pathspec: git stash push -- . ':!src/config.js', quoting the exclusion so bash does not treat ! as history expansion. Alternatively stage the file you want to keep and run git stash push --keep-index.
How do I restore just one file from a stash?
git restore --source=stash@{0} -- path/to/file, or the older git checkout stash@{0} -- path/to/file. This overwrites your working copy of that file without warning and leaves the stash entry intact, so drop the stash yourself when you are done.
Is it better to use a branch instead of a stash?
For anything lasting more than a few minutes, yes. A stash is unnamed, local-only, not pushed, and easy to lose during a rebase or hard reset. A scratch commit on a scratch branch costs one extra command and gives you a name, durability, and something you can push and share.