Skip to content
masterclass Buddy

Git · Command

git stash

git stash saves your uncommitted changes to the working tree and index, then resets them to match HEAD so your directory is clean. You can bring the saved changes back later, either on the same commit or on a different one.

Last updated

How it works

Running git stash with no subcommand is the same as running git stash push. It records your work as a special commit and then rolls the tracked files back to HEAD. That commit has two parents. The first is the HEAD commit. The second is a commit holding the state of the index. The stash commit's own tree holds the state of the working tree. The newest entry is stored at refs/stash, and older entries live in that ref's reflog. You refer to entries as stash@{n}, or just n. Use list and show to inspect entries, apply or pop to restore them, and drop or clear to delete them.

Syntax

git stash [push] [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet] [-u | --include-untracked] [-a | --all] [(-m | --message) <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>...]

Parameters

NameTypeDescription
-m, --message <message>stringAn optional description stored with the entry. Without it, the entry is labelled "WIP on <branch>".
-u, --include-untrackedflagpush/save: also stashes untracked files and then removes them. show: includes untracked files in the diff.
-a, --allflagLike -u, but also stashes and removes ignored files.
-k, --[no-]keep-indexflagLeaves your staged changes in place in the index after stashing.
-S, --stagedflagStashes only the changes that are currently staged.
-p, --patchflagLets you pick, hunk by hunk, which changes to stash. Implies --keep-index.
--indexflagapply/pop: tries to restore the staged changes to the index as well as restoring the working tree.
<pathspec>...pathspecpush only: stashes and rolls back only the files that match.
<stash>stash@{<revision>} or indexThe entry to use with apply, pop, drop, show, branch or export. Defaults to stash@{0}.

Returns

Exits with status 0 on success. If apply, pop or branch hits conflicts, it exits with status 1 and keeps the entry. Any other failure gives a different non-zero status.

Key points

  • Entries form a stack. stash@{0} is the newest, and older ones are reached through the reflog of refs/stash. You can also use time-based names like stash@{2.hours.ago}.
  • By default, untracked files are left out. Add -u to stash them too and remove them from the directory, or -a to also include ignored files.
  • --keep-index stashes everything but leaves what you have staged in place. This lets you build and test exactly the changes you are about to commit.
  • --staged stashes only what is in the index. It works like committing those changes, except they go to the stash instead of the current branch.
  • If you give a pathspec to push, only the matching files are stashed and reset. Every other change stays in your working tree.
  • --patch lets you choose individual hunks to stash interactively, the same way git add -p works.
  • export turns stashes into a chain of commits that you can push to and fetch from another repository. On the other side, import adds them back to the stash list.
  • Scripts can detect a conflicted apply, pop or branch because the command exits with status 1.

Common mistakes

  • If pop runs into conflicts, the entry stays in the list. Resolve the conflicts yourself, then run git stash drop.
  • Entries removed with clear or drop are no longer referenced and can be garbage-collected. The only way to recover them is to search with git fsck --unreachable.
  • git stash save is deprecated and does not accept pathspecs. All of its non-option arguments are joined together into the message.
  • If you use the short form without the word 'push', you must put '--' before any paths. This stops a mistyped subcommand from creating a stash by accident.

Example: Shelve work, hotfix, then resume

# mid-feature, untracked files included
git stash push -u -m "feature: half-done parser"
git stash list

# make the urgent fix on a clean tree
git switch main
# ...edit...
git commit -am "Fix crash on empty input"

# go back and restore work (index too)
git switch feature
if ! git stash pop --index; then
  echo "Conflicts: resolve, then run: git stash drop"
fi

# preview another entry as a patch
git stash show -p stash@{1}

This stashes tracked and untracked changes under a label, makes a fix on another branch, then pops the work back with the staged changes restored, and warns you if the pop hit conflicts.

When to use it

Pulling into a dirty tree

git pull won't run because your local edits conflict with incoming changes. Stash them, pull, then pop them back.

Testing a partial commit

Stage part of your changes and run git stash push --keep-index. Now you can build and test exactly what you are about to commit, then pop the rest.

Parking an unrelated fix

Stage a small unrelated change, run stash push --staged, and pop it later on a separate fixup branch.

Stash no longer applies cleanly

Use git stash branch <name> to restore the stash on a new branch that starts from its original base commit.

Interview questions

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

Both restore a stash entry on top of your current working tree. pop also removes the entry from the list, but apply keeps it. apply also accepts any commit that looks like it was made by stash push or stash create. If pop hits conflicts, it does not drop the entry, so you have to run git stash drop yourself once you've resolved them.

Follow-up: Why would you choose apply in a script? Because the entry survives whatever happens, so you can apply the same stash to several branches, and you only drop it once you know it applied cleanly.

QHow is a stash entry stored internally?

A stash is a commit whose tree holds the state of the working directory. Its first parent is the HEAD commit at the time you stashed. Its second parent is a commit holding the state of the index, and that commit is itself a child of HEAD. The newest stash is stored at refs/stash, and older stashes are entries in that ref's reflog.

Follow-up: Where do untracked files go when you use -u? They are stored in an extra commit attached to the stash. The page doesn't describe that layout in detail, but stash show -u or --only-untracked will show you those files.

QWhich changes does a plain git stash leave behind, and how do you change that?

A plain stash only saves tracked files, both modified and staged. Untracked and ignored files stay where they are. Add -u to include untracked files, or -a to also include ignored ones; either way they are removed from the directory afterwards. You can also narrow a stash with a pathspec, --staged or --patch.

Follow-up: How can you get back a stash you dropped by accident? Run git fsck --unreachable, keep the commit hashes, and pipe them to git log --merges --no-walk --grep=WIP to find likely stash commits. Then apply the one you want, or save it with git stash store.

  • git stash list
  • git stash show
  • git stash pop
  • git stash apply
  • git stash drop
  • git stash branch
  • git stash clear
  • git stash create

Source: Git - git-stash Documentation. Checked 2026-11-02.