Back

A Complete Guide to Git Stash

A Complete Guide to Git Stash

You’re mid-feature, deep in a refactor, when a teammate pings you about a critical bug in production. Your working directory is a mess of half-finished changes. You’re not ready to commit, but you can’t switch branches with uncommitted work sitting around.

This is exactly what git stash is for. This guide covers every git stash command you’ll actually use, how to handle conflicts, and the workflow tips that make stashing feel natural instead of risky.

Key Takeaways

  • git stash saves uncommitted changes to a local stack and restores your working directory to match HEAD, letting you switch contexts without committing half-finished work.
  • By default, stashes only include tracked changes. Use -u for untracked files and -a for ignored ones.
  • Use git stash pop when you want changes back and the stash gone, or git stash apply when you want to keep the stash for reuse.
  • When conflicts during a stash apply get unmanageable, git stash branch creates a new branch from the original commit and applies the stash cleanly.
  • Always add a descriptive message with -m, keep your stash list short, and treat stashes as temporary storage, not backups.

What Is Git Stash?

git stash saves your uncommitted changes—both staged and unstaged—to a local stack and reverts your working directory to match the last commit (HEAD). You can restore those changes later, on the same branch or a different one.

Stashes are local only. They don’t get pushed to your remote with git push, and they aren’t shared with teammates.

What gets stashed by default:

  • Staged changes (index)
  • Unstaged changes to tracked files

What is NOT stashed by default:

  • Untracked files (new files not yet added to Git)
  • Ignored files

Core Git Stash Commands

Save Changes with git stash push

git stash

Plain git stash is shorthand for git stash push. It’s the fastest way to get a clean working directory.

Add a descriptive message so you know what’s in it later:

git stash push -m "WIP: refactor auth middleware"

Note: The older git stash save syntax is deprecated. Use git stash push instead.

Stash Untracked Files

By default, new files you haven’t staged yet are left behind. Use -u to include them:

git stash push -u -m "WIP: new login component"

To also stash files matched by .gitignore, use -a (--all). This is rarely needed but useful when ignored files would interfere with a branch switch or build.

Stash Specific Files

You can stash only certain files using a pathspec:

git stash push -m "WIP: api changes" -- src/api/client.js src/api/utils.js

This leaves everything else in your working directory untouched.

List Your Stashes

git stash list

Output:

stash@{0}: On main: WIP: refactor auth middleware
stash@{1}: WIP on feature/login: 9ab3c12 Add login form

Stashes are stored in a last-in, first-out (LIFO) stack. stash@{0} is always the most recent.

Inspect a Stash Before Applying

git stash show stash@{0}        # summary
git stash show -p stash@{0}     # full diff

Git Stash Pop vs Apply: Which Should You Use?

This is one of the most common points of confusion with git stash commands.

git stash popgit stash apply
Restores changes✅ Yes✅ Yes
Removes from stack✅ Yes (only if apply succeeds without conflict)❌ No
On conflictKeeps stash in stackKeeps stash in stack
Best forOne-time restoreApplying to multiple branches

Use pop when you’re done with the stash and just want your changes back. Use apply when you want to apply the same stash to multiple branches, or when you want to test the result before committing to removing it.

To apply a specific stash:

git stash pop stash@{1}
git stash apply stash@{1}

Restoring Staged State with --index

By default, applying a stash restores all changes as unstaged. If you want to restore the staged/unstaged distinction as it was when you stashed, use --index:

git stash pop --index

Resolving Conflicts When Applying a Stash

If the branch has changed since you stashed, you may hit conflicts:

CONFLICT (content): Merge conflict in src/api/client.js
The stash entry is kept in case you need it again.

Both pop and apply keep the stash in the stack when conflicts occur. To resolve:

  1. Run git status to find conflicted files.
  2. Open each file and resolve the conflict markers.
  3. Stage the resolved files: git add src/api/client.js.
  4. Drop the stash manually once you’re satisfied: git stash drop stash@{0}.

When Conflicts Get Messy: Use git stash branch

If conflicts are too tangled, git stash branch is the cleanest escape hatch. It creates a new branch from the exact commit where you stashed, then applies the stash there. Because the branch starts from the commit where the stash was created, this often avoids conflicts:

git stash branch fix/auth-refactor stash@{0}

If the apply succeeds, the stash is dropped automatically.

Managing and Cleaning Up Stashes

git stash drop stash@{0}   # remove a specific stash
git stash clear            # remove ALL stashes (irreversible)

⚠️ git stash clear is permanent. There’s no undo. Double-check before running it.

Advanced: Partial Stashing and Staged-Only Stash

Interactive patch mode lets you choose which hunks to stash:

git stash push -p

Git walks you through each change and asks whether to stash it. Useful when a file has both related and unrelated changes.

Stash only staged changes (Git 2.35 and later):

git stash push --staged

This stashes what’s in your index and leaves unstaged work in place—handy for isolating a change you want to set aside without losing your current progress.

Keep staged changes in the index while stashing everything else:

git stash push --keep-index

Note that --keep-index still stashes both staged and unstaged changes; it just leaves the staged ones in place in your working directory after the stash.

Recovering a Deleted Git Stash

If you accidentally drop or clear stashes, they may still be recoverable as dangling commits in your repository. Stash entries are stored as merge commits, so you can search for them with:

git fsck --unreachable | grep commit | cut -d' ' -f3 | xargs git log --merges --no-walk --grep=WIP

This lists unreachable merge commits that look like stash entries. Once you find the commit hash you want, restore it with:

git stash apply <commit-hash>

Recovery isn’t guaranteed—Git’s garbage collector will eventually prune unreachable objects—so act quickly.

Transferring Stashes Between Machines

Recent Git versions added git stash export and git stash import, which allow stashes to be transferred using normal fetch and push workflows.

For older Git versions, or for simple one-off transfers, practical alternatives still include:

  • Export as a patch: git stash show -p stash@{0} > my-stash.patch, then apply it elsewhere with git apply my-stash.patch.
  • Commit it on a throwaway branch: create a branch, commit the work, push it to a remote, then pull and reset on the other machine.

Patches are usually the simplest path for one-off transfers.

Git Stash Best Practices

  • Always add a message. git stash push -m "WIP: what and why" saves you from staring at a list of anonymous WIP on main entries.
  • Stash is temporary storage, not a backup. Commit your work when it reaches a logical checkpoint.
  • Keep your stash list short. Review it regularly and drop stashes you no longer need.
  • Pull before popping. Updating your branch before restoring a stash reduces the chance of conflicts.
  • Prefer apply over pop when uncertain. You can always drop the stash manually once you’ve confirmed everything looks right.

Quick Reference: Git Stash Commands

CommandWhat It Does
git stashStash tracked changes (shorthand for push)
git stash push -m "msg"Stash with a descriptive message
git stash push -uInclude untracked files
git stash push -aInclude untracked and ignored files
git stash push -- <path>Stash specific files only
git stash push -pInteractively choose hunks to stash
git stash push --stagedStash only staged changes
git stash push --keep-indexStash everything, but keep staged changes in the index
git stash listList all stashes
git stash show -p stash@{n}Show full diff of a stash
git stash popApply latest stash and remove it
git stash apply stash@{n}Apply a stash without removing it
git stash pop --indexRestore staged/unstaged state
git stash drop stash@{n}Delete a specific stash
git stash clearDelete all stashes
git stash branch <name> [stash]Create a branch from a stash

Conclusion

git stash is one of those commands that feels optional until you really need it—and then it becomes part of your daily workflow. The key habits: always name your stashes, keep the list clean, and reach for git stash branch when conflicts make a simple pop impractical. Used well, stashing keeps your Git history clean and your context switches painless.

FAQs

No. By default, git stash only saves tracked changes—both staged and unstaged modifications to files Git already knows about. New files that haven't been added with git add are left in your working directory. To include them, use git stash push -u or --include-untracked. To also stash files matched by .gitignore, use -a or --all.

Both restore your stashed changes to the working directory. The difference is what happens afterward. git stash pop removes the stash from the stack once it applies cleanly, while git stash apply leaves it in place so you can reapply it later or on another branch. If a conflict occurs during pop, the stash is kept so you don't lose your work.

Often yes, if you act quickly. Stash entries are stored as merge commits, and dropped stashes become unreachable objects that Git's garbage collector will eventually prune. Run git fsck --unreachable to find dangling commits, identify the stash by its WIP message, then restore it with git stash apply followed by the commit hash.

No. Stashes are strictly local and live in your repository's refs/stash reference. They are never included in git push, git fetch, or git pull. If you need to share in-progress work with a teammate, commit it to a temporary branch and push that branch, or export the changes as a patch using git stash show -p.

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay