Git Stash Explained: Shelve Changes Without Committing
Git stash saves uncommitted work to a hidden stack so you can switch branches cleanly. How stash, pop, apply, and stash branches actually work.
git stash takes your uncommitted changes — staged and unstaged — and saves them to a hidden stack, restoring your working directory to match the last commit. It’s the tool for the moment you’re mid-edit, need to switch branches or pull a fix, and don’t want to make a throwaway commit just to clear your working tree.
The basic workflow
git stash # save changes, clean working directory
git checkout main # switch branches freely
git checkout feature-branch
git stash pop # reapply the stash and remove it from the stack
git stash (short for git stash push) bundles your modified tracked files into a commit-like object and resets the working directory to HEAD. git stash pop reapplies the most recent stash and removes it from the stack; git stash apply reapplies it but leaves it on the stack, useful if you want to apply the same stash to more than one branch.
By default, git stash only captures changes to tracked files. Untracked and ignored files are left alone unless you ask for them explicitly:
git stash -u # include untracked files
git stash -a # include untracked and ignored files
This trips people up constantly: you stash, switch branches, come back, and the new files you created are still sitting there because they were never tracked in the first place — which is usually fine, but can be confusing if you expected a clean slate.
Managing multiple stashes
Stashes stack — you can stash more than once without popping in between, and each one gets an index:
git stash list
# stash@{0}: WIP on feature-branch: a1b2c3d Add validation
# stash@{1}: WIP on main: e4f5g6h Fix typo
git stash show stash@{1} # summary of what changed
git stash show -p stash@{1} # full diff
git stash apply stash@{1} # apply a specific stash, not just the latest
git stash drop stash@{1} # discard a stash without applying it
git stash clear # discard all stashes
Give a stash a name if you’ll have more than one in flight, since “WIP on feature-branch” descriptions all start to look the same after a few days:
git stash push -m "half-finished pagination logic"
Stashing part of your changes
git stash push accepts pathspecs, so you can stash only some files and leave the rest staged or in the working directory:
git stash push -- src/api/users.ts
For finer control — stashing individual hunks within a file — use git stash -p, which walks through each hunk and asks whether to include it, the same interactive prompt used by git add -p.
Turning a stash into a branch
If a stash conflicts badly with the branch you’re trying to apply it to, git stash branch creates a new branch from the commit the stash was taken on, checks it out, and applies the stash there — sidestepping the conflict entirely:
git stash branch new-feature stash@{0}
This is the fix for the common failure mode where you stash on one commit, do a bunch of unrelated work, then try to pop the stash back onto a branch that’s since diverged and no longer applies cleanly.
How it compares to alternatives
| git stash | commit + amend | worktree | |
|---|---|---|---|
| Speed | Instant | Requires a message, still visible in log | Requires a new checkout |
| Pollutes history | No | Yes, until squashed | No |
| Works across branches | Yes | Yes, via cherry-pick | N/A — separate directory entirely |
| Good for long-lived parallel work | No | No | Yes |
For genuinely long-running parallel work — not just “I need to switch branches for five minutes” — a git worktree is usually the better tool, since it gives you a second working directory instead of a single directory juggling saved states. Stash is for short interruptions; worktrees are for running two branches side by side.
Where stashes live and how they’re lost
Stashes are stored as commit objects referenced by refs/stash, which means they’re subject to garbage collection like any unreferenced commit once dropped — git stash drop doesn’t shred the data instantly, but don’t rely on recovering it either. If you’ve popped or dropped a stash by mistake, git fsck --unreachable can sometimes surface the dangling commit before garbage collection sweeps it away, but this isn’t a substitute for actually committing work you care about. Stash is explicitly meant for transient, disposable state, not long-term storage — if something needs to survive a git stash clear or a machine wipe, commit it, even to a scratch branch. That distinction matters more once you’re doing a rebase or a cherry-pick across branches, where an uncommitted stash can quietly get left behind on the wrong checkout.
The takeaway
git stash is a fast, local escape hatch for uncommitted work you’re not ready to commit but don’t want to lose. Use plain stash/pop for the common case of switching branches and coming right back, reach for -u when untracked files matter, name your stashes once you have more than one, and use stash branch when a stash no longer applies cleanly to where you’re trying to put it. For anything that needs to survive longer than a few minutes or move across more than one branch, commit it instead.
Tagged
Keep reading
The Lycoris Team · · 4 min read What Is Git Reflog? Recovering Lost Commits
Git reflog records every place HEAD and branch tips have pointed, letting you recover commits that look lost after a reset, rebase, or deleted branch.
The Lycoris Team · · 5 min read What Are Conventional Commits? A Commit Convention
Conventional Commits structures commit messages as type(scope): description so tools can auto-generate changelogs and version bumps from git history.
The Lycoris Team · · 4 min read Git Cherry-Pick Explained: Copying Commits Between Branches
Git cherry-pick applies one commit's changes onto a different branch without merging the whole branch. How it works, and when to use it instead of merging.