You’re halfway through a change, and need to switch branches to fix something urgent, or pull new commits, but your work isn’t ready to commit. git stash saves your uncommitted changes on a stack, and gives you a clean working directory. When you’re back, you reapply them.

Stash and restore

git stash push -m "WIP: invoice export"     # save changes (tracked files)
git status                                   # clean
git switch hotfix/login && …                 # do other work
git switch feature/invoice-export
git stash pop                                # reapply and remove from the stash

git stash without arguments is the same as git stash push, but a message (-m) makes the list readable later.

What gets stashed

By default: modified tracked files, staged and unstaged. Not included:

git stash push -u -m "with new files"     # -u / --include-untracked: new files too
git stash push -a                         # -a / --all: also ignored files (rarely needed)

Forgetting -u is a common surprise: new files stay behind in the working directory.

List and inspect

git stash list
# stash@{0}: On feature/invoice-export: WIP: invoice export
# stash@{1}: WIP on main: 3f2a1c9 Fix typo

git stash show stash@{1}          # files changed
git stash show -p stash@{1}       # full diff

apply vs pop

Command Effect
git stash apply [stash@{n}] Reapply, keep the stash entry
git stash pop [stash@{n}] Reapply, and remove it if successful
git stash drop stash@{n} Delete one entry
git stash clear Delete all entries (careful)

If applying causes conflicts, pop keeps the stash entry, so nothing is lost. Resolve the conflicts, git add the files, then git stash drop.

git stash apply --index also restores what was staged versus unstaged.

Stash only some changes

git stash push -m "only config" -- config/app.php     # specific files
git stash push -p                                     # interactively choose hunks
git stash push --staged                               # only staged changes (Git 2.35+)

Turn a stash into a branch

If the branch has moved on, and the stash no longer applies cleanly:

git stash branch feature/invoice-export-v2 stash@{0}

This creates a branch at the commit where you stashed, applies the stash there, and drops it if successful.

Recover a dropped stash

Dropped or cleared stashes are unreferenced commits, and are recoverable for a while:

git fsck --no-reflog | awk '/dangling commit/ {print $3}' | \
  xargs -I{} git log -1 --format='%h %s' {} | grep -i "WIP\|On "
git stash apply <commit-hash>

See undo the last commit.

Good habits

  • Stashes are local: they aren’t pushed, and they’re easy to forget. For anything longer than a quick switch, prefer a WIP commit on a branch (git commit -m "WIP", later amended or squashed).
  • Use git worktree add ../hotfix hotfix/login to work on two branches at once, without stashing at all.
  • Clean up old entries with git stash list from time to time.

Quick reference

Task Command
Save with message git stash push -m "msg"
Include new files git stash push -u
List git stash list
Show diff git stash show -p stash@{0}
Reapply and remove git stash pop
Reapply, keep git stash apply
Partial git stash push -p / -- <files>
To branch git stash branch <name>

Related: git cherry-pick and Git commands cheat sheet.

  • Git
  • Command Line
  • Productivity