You're mid-change on one thing when something more urgent lands — a hotfix, a branch switch, a rebase you can't start with a dirty working tree — and none of your current edits are ready to be a commit yet. git stash is the command for exactly that moment: it takes your uncommitted changes, tracked and optionally untracked, and tucks them away on a stack that lives outside any branch, leaving your working tree clean so you can switch context immediately and come back later. Whether you typed "git and stash," "what does git stash do," or landed here mid-task already knowing the command but not the details, this guide covers all of it: saving, naming, the git stash and pop round trip, restoring a single file, telling apply apart from pop, and the part most tutorials skip entirely — how to actually look inside a stash before you restore it. If what you actually want is to commit early and fix it up afterward instead of stashing, that decision and the commands for it are covered in the git undo last commit guide.

Quick Answer: What Git Stash Does in One Line

git stash saves your uncommitted changes to a hidden stack and resets your working tree to match HEAD, so you get a clean slate without committing or losing anything. Pick your exact scenario below — full explanations follow in the linked sections.

Situation Command Notes
Stash all tracked changes git stash Shorthand for git stash push
Stash with a descriptive message git stash push -m "message" Otherwise git auto-generates one from the branch and commit
Also stash untracked files git stash push -u Ignored files still excluded
Stash literally everything, ignored files too git stash push -a Rarely needed — usually means .gitignore is wrong
Stash a single file git stash push -- path/to/file Other modified files stay in the working tree
List every stash git stash list Newest is stash@{0}
Preview a stash before restoring git stash show -p stash@{0} Full diff, changes nothing
Restore and remove from the stack git stash pop Skips the removal step if a conflict occurs
Restore but keep it on the stack git stash apply Safer when you might need the same stash again
Delete one stash git stash drop stash@{1} Defaults to the newest entry if no index is given
Delete every stash git stash clear Irreversible through normal git commands

The first two rows answer the most common phrasings of this question — "how to stash changes git" and "how to use git stash" — and for most sessions the whole thing is two commands typed hours apart:

# Something urgent came up — park the work in progress
git stash

# Back on it later — bring the changes right back
git stash pop

Everything past that pair is about the parts that bite later: what a stash actually is, which files a plain stash leaves behind, how to look inside one before restoring it, and what happens when a pop hits a conflict.

What Does Git Stash Do? The Mental Model

The honest answer to "what does git stash do" and "how does git stash work" is that it wraps your uncommitted changes into one or more real commit objects, then points a special reference — refs/stash — at the newest one, chaining older entries behind it as parents. That structure is a stack: last in, first out. stash@{0} is always the most recent entry, stash@{1} the one before it, and so on. None of these commits belong to any branch, which is exactly why git stash can leave your working tree spotless — the changes still exist, just parked somewhere git log on your branch will never show them.

Under the hood, a single stash entry is actually built from up to three commits: one capturing your working-tree state, one capturing whatever was staged in the index at the time, and — only if you stashed with -u or -a — a third capturing untracked files. Git ties all of them together behind the one reference you interact with, so from the command line a stash looks like a single unit even though internally it's a small commit graph. That layout is the mechanical answer to how does git stash work at the object level, and it's described in the same terms under the "Discussion" section of git's official git-stash documentation. As of Git 2.22, git stash itself was rewritten from a shell script into a C builtin, which is why it's noticeably faster on large repositories than it used to be — the behavior didn't change, just the implementation.

By default, a plain git stash grabs every tracked file with modifications — both staged and unstaged changes, which answers "git stash unstaged" directly: unstaged edits are included automatically, you don't need a special flag for them. There's no separate git stash unstaged subcommand to hunt for — the default already takes both sides of the index. What it leaves behind by default is untracked and ignored files, covered in its own section below, since that's the single most common surprise people run into the first time a stash "loses" a new file.

git stash is a LIFO stack, not a branch The stack (LIFO) Anatomy of one entry stash@{0} — newest apply / pop read this first stash@{1} stash@{2} (oldest) working-tree commit index (staged) commit untracked commit (-u/-a only) = one entry New stash entries are pushed on top — apply/pop always start at stash@{0}, the newest one.
Every stash lives on a LIFO stack outside any branch: stash@{0} is always the newest and the default target for apply/pop. Internally, one entry bundles up to three commits — working tree, index, and (with -u/-a) untracked files — behind a single refs/stash reference.

How to Stash Changes: git stash push

git stash push is the full command; bare git stash with no subcommand is shorthand for it, and both do the same thing — this is the direct answer to "how to stash changes git" and "how to use git stash." You'll also see git stash save "message" in older tutorials: it's the predecessor command, deprecated in favor of push since Git 2.13, and it's missing push's pathspec support (no stashing just one file). Use push going forward; save still works for backward compatibility but nothing here needs it.

$ git status
On branch main
Changes not staged for commit:
  modified:   src/api/client.ts
  modified:   src/api/retry.ts

$ git stash
Saved working directory and index state WIP on main: 4a1b2c3 add retry config
$ git status
On branch main
nothing to commit, working tree clean

A git stash example worth internalizing: after that git stash runs, both files revert to exactly how they looked at your last commit, the changes aren't gone, they're saved as stash@{0} and retrievable with apply or pop whenever you're ready. One flag worth knowing early: --keep-index stashes everything as usual but leaves your staged changes staged in the working tree afterward, useful when you want a clean unstaged area but need to keep testing against what's currently in the index.

# Standard stash — working tree and index both reset to HEAD
git stash push

# Stash everything, but leave staged changes staged afterward too
git stash push --keep-index

That's the whole of "how to use git stash" in the common case: one command to park the work, one to bring it back. Every git stash example past this point is a variation on scope — which files go in — or on what happens to the entry once you've restored it.

Naming Stashes and Reading git stash list

Without a message, git auto-generates one in the form WIP on <branch>: <short-sha> <subject-of-HEAD>, which is fine for one stash but gets confusing fast once you have three or four sitting around with nearly identical auto-generated text. That's what the git stash with message form is for: pass -m and the text is yours.

git stash push -m "wip: retry backoff before the auth hotfix"

git stash list is how you read back what's saved, newest first, and it's the answer to "git stash name" in the sense that matters most — the message you gave it (or the auto-generated one) is exactly what shows up here:

$ git stash list
stash@{0}: On main: wip: retry backoff before the auth hotfix
stash@{1}: WIP on feature/csv-export: 9f8e7d6 add header row option

There's no command to rename a stash after the fact — a git stash name is set once, at creation time, and git stash with message only works at the moment you create the entry. If a name turns out to be wrong or unhelpful, the practical fix is to pop or apply the stash, then re-stash it with -m and the message you actually wanted; there's no in-place edit, unlike amending a regular commit's message after the fact.

Stashing Untracked and Ignored Files: -u vs -a

By default, git stash only touches tracked files — anything git status lists under "Untracked files" stays exactly where it is, untouched, when you run a plain stash. This trips people up constantly: you stash, switch branches, and a brand-new file you were working on is still sitting in your working tree, which can look like it "leaked" across the stash boundary when really it was never included in the first place.

Two flags change that, and they cover different scope:

  • -u / --include-untracked — adds untracked files (new files git doesn't know about yet) into the stash, but still leaves anything matched by .gitignore alone. This is the answer to "git stash include untracked" and "git stash untracked" specifically.
  • -a / --all — adds untracked and ignored files both. This is the wider net, and it's rarely what you actually want; reach for it only when you deliberately need to stash build artifacts or generated files alongside your real changes, since it's easy to accidentally sweep up things like node_modules or .env if your ignore rules are broad.
# Include new (untracked) files, skip anything gitignored
git stash push -u -m "wip: new csv parser module"

# Include everything, including ignored files — use sparingly
git stash push -a -m "wip: full snapshot before cleanup"

Both are per-command flags, not settings: the git stash untracked question comes down to remembering -u at the moment you stash, because the default scope never widens on its own. One further consequence worth knowing before it surprises you: when you later pop or apply a stash created with git stash include untracked semantics, the files that were untracked come back as untracked again — stashing them doesn't retroactively start tracking them, it just preserves their content across the round trip.

Stash scope: default vs -u vs -a tracked + modified -a / --all + ignored files too (rare) -u / --include-untracked + untracked (new) files default: git stash tracked + modified only -a always implies everything -u does, plus files matched by .gitignore.
Plain git stash covers only tracked, modified files. -u / --include-untracked widens that to new untracked files. -a / --all widens it once more to include ignored files too — each flag is a strict superset of the one before it.

Stashing Certain Files Only

git stash push accepts a pathspec, which is the whole mechanism behind "git stash certain files" instead of everything, and the direct fix for "git stash one file," "git stash single file," and "stash specific files git" — every version of the same question. Put a double dash before the path(s) so git doesn't confuse a file name with a flag:

# Stash changes to one file only — everything else stays in the working tree
git stash push -- src/api/client.ts

# Stash a specific set of files
git stash push -- src/api/client.ts src/api/retry.ts

# Stash only what's currently staged (git 2.35+)
git stash push --staged

--staged narrows scope the other direction: instead of picking files by path, it stashes only whatever you've already git add-ed, leaving unstaged edits — even in the same files — sitting in the working tree. For finer control than a whole file at a time, -p (or --patch) walks through your changes hunk by hunk and lets you choose y/n for each one interactively, the same review flow git add -p uses for staging:

# Interactively choose which hunks to stash
git stash push -p

This combination — pathspec for whole files, --staged for the index only, and -p for individual hunks — covers "git stash certain files" completely: pick the granularity that matches how mixed your working tree actually is. Whichever way you phrased it going in — git stash file, git stash one file, or git stash single file — the mechanism is that one pathspec argument: git stash push -- <path>.

Inspect Before You Restore: git stash show and git diff

This is the step most tutorials skip, and it's the one that actually prevents mistakes: you can look at exactly what's inside a stash without touching your working tree at all, as many times as you want, before deciding whether to bring it back.

# Summary: which files changed, how many lines each
git stash show stash@{0}
#  src/api/client.ts | 12 ++++++------
#  src/api/retry.ts  |  4 ++++
#  2 files changed, 10 insertions(+), 6 deletions(-)

# Full diff, every changed line, unified format
git stash show -p stash@{0}

# Compare the stash against your CURRENT working tree, not just its own parent
git diff stash@{0}

The distinction between those last two matters more than it looks: git stash show -p shows the diff the stash recorded — the change relative to the commit you were on when you stashed. git diff stash@{0} shows what would happen if you applied it right now, against whatever your working tree looks like at this exact moment — which can differ if you've made other commits or edits since stashing. If several stashes look nearly identical in git stash list, running git stash show -p against each one is the fastest way to tell them apart rather than guessing from the auto-generated message. git stash show -p outputs a standard unified diff, the same format git diff and plain diff -u produce.

For a longer or more tangled diff, reading it directly in the terminal gets hard fast. Copy the output of git stash show -p stash@{1} into one pane of Diff Checker, a free Chrome extension, and paste the current version of the same file into the other pane — its Monaco-based editor lines the two up side by side (or as a unified view) and recomputes as you edit either side, with no upload and no setup. That combination is exactly the "preview before you commit to restoring" workflow: confirm what a git stash apply would actually bring back before you run it, which matters most when a pop already conflicted once and you need to compare the conflicted file against the stashed version to figure out what's still different. For comparing whole files this way in general, see the git diff between two files guide.

Two commands, two different baselines c3d4e5f (T0) HEAD when stashed stash@{0} the stash entry current working tree (right now) git stash show -p — diff vs recorded parent (T0) git diff stash@{0} — diff vs the working tree right now
git stash show -p compares the stash against the commit you were on when you stashed (T0) — a fixed baseline. git diff stash@{0} compares the same stash against your working tree at this exact moment, which can differ if you've committed or edited since.

Restoring a Stash: git stash apply vs git stash pop

Both commands do the same restore; they differ only in what happens to the stack entry afterward, which is the entire answer to "git stash pop vs apply" and "how to unstash git."

  • git stash apply restores the stash's changes into your working tree and keeps the entry on the stack. Use it when you might need the same stash again — applying it to a second branch, or as a safety net while you're not fully sure the restore is right.
  • git stash pop restores the changes and then removes the entry — it's apply immediately followed by drop, and it's the more common choice once you're done with a stash for good. This literally is the "git stash and pop" and "restore git stash" workflow most people want by default.
# Restore the newest stash, keep it on the stack
git stash apply

# Restore the newest stash, remove it once restored cleanly
git stash pop

# Target a specific one instead of the default newest — stash@{0}
git stash apply stash@{2}
git stash pop stash@{2}

Neither command defaults to anything other than stash@{0} — the newest entry — so "git stash apply specific stash," "git stash pop specific stash," and the bare "git stash apply stash" phrasing all come down to the same thing: naming the index explicitly, as shown above. One more flag worth knowing: plain apply or pop only restores your working tree; add --index to also restore which changes were staged versus unstaged at stash time, instead of dumping everything back as unstaged modifications:

# Restore working tree AND staging state exactly as they were
git stash apply --index

The one-line rule for git stash pop vs apply: pop is apply plus drop, so reach for apply whenever there's a chance you'll want a second attempt at the same restore. Either command is a valid way to restore git stash content into a working tree — the only difference is what's left on the stack when it's done.

apply keeps the entry, pop removes it git stash apply git stash pop stash@{0} apply working tree restored stash@{0} — kept still on the stack stash@{0} pop working tree restored stash@{0} — removed dropped after clean restore Same restore either way — apply leaves a safety net, pop cleans up once it succeeds.
Both commands restore the stash's changes into your working tree identically. The difference is entirely afterward: apply leaves stash@{0} on the stack as a safety net, pop removes it — but only once the restore completes cleanly.

Restoring a Single File From a Stash

Sometimes you don't want the whole stash back — just one file out of several that changed. git checkout can pull a single path out of any commit-like reference, stashes included, without touching anything else in your working tree:

# Restore just one file from a stash, leave everything else alone
git checkout stash@{0} -- src/api/retry.ts

# Modern equivalent (git 2.23+), same effect, clearer name
git restore --source=stash@{0} -- src/api/retry.ts

Both forms leave the stash entry untouched on the stack — this is a copy operation, not apply or pop, so nothing is removed and the rest of the stash is still there if you need another file from it later. It's the cleanest fix when a stash bundles several files together but a full apply would create conflicts you don't want to deal with for files you don't actually need restored right now.

Deleting Stashes: git stash drop and git stash clear

Two commands cover every version of "git stash delete," "git stash remove," and "git clear stash":

# Delete one specific stash entry
git stash drop stash@{1}

# Delete the newest entry (default target when no index is given)
git stash drop

# Delete EVERY stash entry at once
git stash clear

drop removes exactly one entry and shifts the indices of everything below it up by one, so re-check git stash list before dropping a second stash by index in the same session. clear is the blunt instrument — it wipes the entire stack in one command, with no per-entry confirmation, so it's worth running git stash list first to make sure nothing on it is still needed. There is no git stash delete and no git stash remove subcommand to go looking for — those two are the only ones that exist, and "git clear stash" is just git stash clear with the words in a different order. Neither command is reversible through normal git usage in the moment you run it, though the next section covers the narrow recovery window that still exists right after.

When git stash pop Hits a Conflict

This is the detail that catches people off guard: if the changes in a stash can't merge cleanly into your current working tree — you've edited the same lines since stashing, or switched to a branch with diverging content — git stash pop leaves conflict markers in the affected files, exactly like a conflicted merge. Critically, the stash entry is not dropped when that happens. Pop only removes the entry after a clean restore; on conflict, the drop step is skipped entirely so your stashed work never disappears into a half-merged file with no backup.

$ git stash pop
Auto-merging src/api/client.ts
CONFLICT (content): Merge conflict in src/api/client.ts
$ git stash list
stash@{0}: On main: wip: retry backoff before the auth hotfix

Notice the stash is still listed after the conflict — that's the safety net. From here:

  • Open the conflicted file(s) and resolve the markers, same as any merge conflict.
  • Stage the resolution with git add <file>. There's no git stash --continue; once files are resolved and staged, the pop is effectively done.
  • Decide separately whether to run git stash drop stash@{0} to clean up the now-redundant entry, or leave it a little longer as a fallback until you're confident the resolution is correct.
  • To bail out of the conflicted state entirely and try again later, discard the failed merge with a hard reset back to HEAD — the stash itself is untouched by this, since it was never dropped in the first place.
A conflicted pop keeps the stash, even though the merge failed $ git stash pop CONFLICT (content) <<<<<<< Updated upstream (your current changes) ======= (changes from stash@{0}) >>>>>>> stash@{0} Working tree has conflict markers resolve, then git add — same as any merge stash@{0} still on the stack drop step skipped — nothing lost Pop only drops the stash after a clean restore — on conflict, the drop step never runs.
When git stash pop can't merge cleanly, it leaves conflict markers in the working tree exactly like a conflicted merge — but the drop step is skipped entirely, so stash@{0} stays on the stack as a safety net until you resolve things and decide to drop it yourself.

git stash branch and Recovering a Dropped Stash

git stash branch <new-branch-name> [stash] solves a specific version of the conflict problem above pre-emptively: it creates a new branch starting from the commit that was HEAD when the stash was made, checks that branch out, then pops the stash onto it. Because the branch starts from the exact commit the stash was created against, the apply step can't conflict due to divergence — it's the same starting point the stash already expects. It's the same escape hatch the Pro Git "Stashing and Cleaning" chapter recommends when a stash refuses to reapply cleanly.

git stash branch fix/retry-backoff stash@{0}

This is the right tool specifically when your current branch has moved on since you stashed — new commits landed, or you switched branches entirely — and a plain pop would conflict for reasons that have nothing to do with the actual content, just a diverged base. Once that branch has served its purpose, cleaning it up afterward is the same local branch deletion workflow you'd use for any short-lived branch. Note the boundary here: stashing moves uncommitted work between branches, so if the change is already a commit sitting on the wrong branch, copying that commit across is a cherry-pick, not a stash.

Recovering a stash after drop or clear works because dropping a stash doesn't destroy the underlying commit objects immediately — it only removes the reference pointing at them. Until garbage collection actually runs, those commits are "dangling" but still on disk, and git fsck can find them:

# List unreachable commit objects, including dropped stashes
git fsck --no-reflogs | grep commit

# Inspect a candidate to confirm it's the right one
git show <sha>

# Recover it — either re-apply directly or save it to a branch first
git stash apply <sha>
git branch recovered-stash <sha>

This only works before automatic garbage collection prunes unreachable objects — usually a window of about two weeks by default, or sooner if something explicitly triggers git gc. There's no guarantee past that point, which is the practical argument for naming stashes clearly with -m and checking git stash list before running clear, rather than relying on fsck as a routine safety net.

Drop removes the pointer; the commit lingers until git gc Before: git stash drop After: git stash drop refs/stash commit X (stash@{0}) refs/stash — removed commit X dangling — ~2 wks until gc Recover before gc runs: git fsck --no-reflogs finds commit X apply <sha> / branch <name> Dropping only removes the reference — the object survives, dangling, until git gc prunes it.
git stash drop only removes the refs/stash pointer — the commit object it pointed to survives on disk as a dangling commit until garbage collection eventually prunes it, usually after about two weeks. Until then, git fsck --no-reflogs can find it, and git stash apply or git branch can bring it back.

Viewing Stashes on GitHub (You Can't — Here's Why)

Directly: you cannot view a stash on GitHub, and there's no setting or workaround that changes that. A stash lives entirely inside your local .git directory — as a refs/stash reference and the commit objects it points to — and git push has no mechanism that transmits it anywhere. It isn't a branch, isn't a tag, and never gets included in a normal push, no matter what remote you're pushing to. GitHub, GitLab, and Bitbucket all inherit this the same way: their web UIs have no concept of a "stash" at all, because the underlying git protocol they read from never sees one — which is why a "github view stash" search turns up no page, tab, or button anywhere in the interface.

If you actually need to hand stashed work to someone else or view it on another machine, two practical options replace "github view stash" as a goal:

  • Export it as a plain diff file — git stash show -p stash@{0} > wip.patch — and share that file directly; anyone can apply it with git apply wip.patch.
  • Turn it into a real branch and push that instead — git stash branch temp-wip followed by git push -u origin temp-wip — which is genuinely visible on GitHub because it's an ordinary branch, not a stash anymore.

Git Stash Commands at a Glance

Five commands, side by side, so the choice between them is a lookup instead of a guess:

Command Effect on the stack Effect on your working tree Use when
git stash apply Entry stays on the stack Restores the changes (add --index for staged state too) You might need this stash again, or want a safety net
git stash pop Entry removed — only if the restore was clean Restores the changes You're done with the stash for good
git stash drop One entry removed Unchanged Discard a specific stash you don't need
git stash clear Every entry removed Unchanged Wipe the whole stack at once
git stash branch <name> Entry removed, if the pop onto the new branch succeeds New branch created and checked out, then the stash is applied there Your current branch has diverged since you stashed and a plain pop would conflict

Frequently Asked Questions

How do I preview a stash's contents before applying it?

Run git stash show stash@{0} for a diffstat summary of which files changed, or git stash show -p stash@{0} for the full unified diff of every line. Neither command touches your working tree, so you can inspect a stash as many times as you want before deciding to restore it. For the most complete picture when several similar-looking stashes exist, git diff stash@{0} compares the stash directly against your current working tree rather than against the commit it was created from, showing exactly what would change if you applied it right now. Pasting that diff alongside your current file into a side-by-side text comparison tool makes the difference even easier to scan when the change is more than a few lines.

What is the difference between git stash pop and git stash apply?

git stash apply restores the stashed changes into your working tree but leaves the stash entry sitting on the stack afterward, so you can apply the same stash again elsewhere. git stash pop does the same restore and then deletes the stash entry in one step — it's apply plus drop, and it's the more common choice once you're confident you won't need that stash a second time. The one exception: if pop's restore hits a merge conflict, the drop step is skipped and the stash entry survives on the stack, so a failed pop never silently deletes your stashed work.

How do I apply a specific stash when I have several stashed at once?

Run git stash list first to see every entry with its index — stash@{0} is the most recently created, stash@{1} the one before that, and so on. Pass that reference explicitly to target it: git stash apply stash@{2} or git stash pop stash@{2} restores that specific entry regardless of where it sits in the stack, rather than defaulting to the newest one. Indices shift as you drop or pop entries, so re-run git stash list after any change before you reference an index again.

How do I stash just one file instead of everything?

Pass the file's path after a double dash: git stash push -- path/to/file.js stashes only the changes to that file and leaves every other modification sitting in your working tree untouched. List multiple paths to stash a specific set of files in one command, or add -p (git stash push -p) to interactively choose individual hunks within a file rather than the whole file at once. This is the direct answer to stashing a single file or a handful of specific files without disturbing unrelated work in progress.

What happens if git stash pop hits a conflict — is the stash removed?

No — this is the detail most guides skip. When the stashed changes can't merge cleanly into your current working tree, git leaves conflict markers in the affected files and stops, exactly like a conflicted merge, but it deliberately does not drop the stash entry. That's intentional: dropping it would mean the only copy of your stashed work is stuck half-merged into files you're still resolving. Resolve the conflicts, stage the results with git add, and then decide separately whether to run git stash drop to clean up the now-redundant entry, or leave it as a backup until you're sure the resolution is correct.