TechEarl

How to Use git stash

How to use git stash to set work aside without committing. Save, list, pop, apply, and drop stashes, stash untracked files, do a partial stash, and switch branches cleanly.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
How to use git stash to save uncommitted changes, then pop, apply, list, and drop them, including stashing untracked files and partial stashes.

git stash takes the changes in your working tree, tucks them away on a stack, and gives you back a clean working directory matching the last commit. You get your work back later with git stash pop. The whole point is to set unfinished work aside without committing it, usually because something more urgent just came up.

bash
git stash          # save your changes, clean the working tree
git stash pop       # bring the most recent stash back and remove it from the stack
Shelving and restoring work with git stash and git stash pop
git stash shelves your changes; git stash pop brings them back.

That is the ninety-percent answer. The rest of this page covers the difference between pop and apply, how to stash files Git is not tracking yet, how to stash only some of your changes, and the everyday pattern of stashing so you can switch branches.

What git stash actually saves

By default git stash saves two things: changes to files Git already tracks, whether or not you have run git add on them, and your staged changes. It then resets your working tree to match HEAD, so the directory looks like a fresh checkout of your last commit.

What it does not save by default:

So if you stash and then notice a brand-new file is still sitting there, that is expected. Git only stashed the things it was already watching.

If the distinction between tracked, staged, and untracked is fuzzy, the Git staging area walkthrough is worth reading first. Everything git stash does is built on those states.

Saving and restoring: pop vs apply

The two ways to get your work back are git stash pop and git stash apply. They both reapply the stashed changes to your working tree. The difference is whether the stash entry sticks around afterward.

CommandReapplies changesKeeps the stash entryUse when
git stash popYesNo (removes it from the stack)The normal case: you want your work back and you are done with the stash
git stash applyYesYes (entry stays on the stack)You want to apply the same stash to more than one branch, or you want a safety copy until you confirm it applied cleanly

In day-to-day work, pop is what you want. Reach for apply when you want to keep the stash around, then delete it yourself with git stash drop once you are sure it landed correctly.

bash
git stash apply     # reapply the latest stash, but leave it on the stack
git stash drop       # then remove it manually when you are happy

One caution with pop: if reapplying the stash causes a merge conflict, Git does not drop the stash entry. That is deliberate, so you do not lose the work while resolving the conflict. Resolve it the same way you would resolve any merge conflict, then drop the stash by hand.

Naming a stash so you can find it later

A bare git stash records a generic message like WIP on main. If you stash often, give the entry a label so future-you knows what it holds.

bash
git stash save "half-finished login form"

git stash save -m "msg" (or just git stash save "msg") is the form for naming a stash. Plain git stash records a generic message; save lets you attach your own. Updated: Git 2.13 (May 2017) added git stash push, which deprecates save and reads more naturally (git stash push -m "half-finished login form"). Either works on a current Git; reach for push -m on anything modern.

Listing, inspecting, and dropping stashes

Stashes live on a stack, so you can have several at once. List them with:

bash
git stash list
text
stash@{0}: On main: half-finished login form
stash@{1}: WIP on feature/api: 9c3f1a2 add request logging

The most recent stash is always stash@{0}. To see what a particular stash contains without applying it:

bash
git stash show stash@{1}          # summary of changed files
git stash show -p stash@{1}        # the full diff

To apply or pop a specific stash rather than the latest, name it:

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

To delete one stash, or clear the whole stack:

bash
git stash drop stash@{1}     # remove a single entry
git stash clear               # remove every stash (no undo, be careful)

git stash clear does not warn you. If you are unsure whether you still need something on the stack, list and inspect first.

Stashing untracked files

Because git stash ignores untracked files by default, a new file you just created stays in your working tree after a stash. To include untracked files, add -u (or the long form --include-untracked):

bash
git stash -u        # stash tracked changes AND untracked files

To go further and also include files matched by .gitignore, use -a (--all):

bash
git stash -a        # stash everything, including ignored files

I reach for -a rarely. Ignored files are usually build output or local config you do not want moving around. Most of the time -u is the one you want when a stash leaves stray new files behind.

Stashing only some of your changes

Sometimes you only want to set aside part of your work and keep editing the rest. The -p (--patch) flag walks you through each change and asks, hunk by hunk, whether to stash it:

bash
git stash -p

Git shows each chunk of the diff and waits for a key. The ones worth knowing:

text
y - stash this hunk
n - do not stash this hunk
s - split this hunk into smaller pieces
q - quit, stash nothing more
? - show the full list of options

This is the same interactive patch interface git add -p uses, so if you already split commits with the staging area, it will feel familiar. Partial stashing is handy when one file holds two unrelated edits and you only want to hide one of them.

The pattern everyone uses: stash to switch branches

Here is the situation git stash was built for. You are partway through a change on one branch, and a bug report comes in that you need to fix on another branch right now. You are not ready to commit your half-done work, but Git will not let you switch branches if the checkout would overwrite your local edits (see local changes would be overwritten for that exact error).

Stash, switch, fix, switch back, pop:

bash
git stash                       # set your half-done work aside
git checkout main               # move to the branch with the bug
# ... fix the urgent bug, commit it, push ...
git checkout feature/login      # back to where you were
git stash pop                   # your half-done work returns

On a solo project that round trip is the whole story. On a team it sits inside a wider branching plan: the same instinct to keep a clean main branch and to follow one of the three branching strategies teams use is what makes the interruption above land on the right branch in the first place.

Updated: Git 2.23 (August 2019) added git switch as a clearer, dedicated alias for changing branches (git switch main / git switch feature/login). It does the same thing as git checkout <branch> here; use whichever your Git supports.

That round trip is the everyday use of stash. Your unfinished change never touches the commit history; it just rides along on the stack while you deal with the interruption.

Two honest caveats. Stash is for short detours, not long-term storage. A stash that sits for a week is a change you have half-forgotten and never reviewed; if work is worth keeping for any length of time, make a throwaway branch and a real commit instead, with a decent commit message. And a stash is local only: it never gets pushed to a remote, so it is not a backup. If you would be upset to lose it, commit it.

Recovering a stash you dropped by accident

If you git stash drop or git stash clear and then realize you needed that work, it is usually not gone yet. Stashes are commits under the hood, and dropped commits hang around in the reflog until garbage collection. The full recovery walkthrough is in recovering lost commits with git reflog, but the short version is to find the dangling stash commit and apply it:

bash
git fsck --no-reflogs | grep commit     # find dangling commits
git stash apply <commit-hash>            # reapply the one you recognise

Replace the hash with the dangling commit that matches your lost work. This is a fallback, not a habit. The reliable move is to not clear a stack you have not inspected.

Where stash fits among the "undo" commands

Stash is one of several ways to deal with uncommitted work, and people often confuse it with discarding or resetting. They do different things:

GoalCommandKeeps your changes
Set work aside to bring back latergit stashYes (on the stack)
Throw work away entirelygit restore . (see discard local changes)No
Move a finished change into historygit commitYes (as a commit)
Undo a commit you already madedepends; see undo the last commit and reset vs revertdepends

If you want the work back later, stash. If you want it gone, discard. If it is done, commit. Reaching for stash to "undo" a commit is the common mistake; stash only ever touches the working tree and the index, never the commit history.

New to Git altogether? Start with Git for Beginners, which walks through the whole picture (working tree, staging area, commits, branches) that stash sits on top of.

Sources

Authoritative references this article was fact-checked against.

Tagsgit stashGitVersion Controlgit stash popgit stash applyDevOps

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

How to Use Git with WordPress

How to put a WordPress project under Git: what to track vs ignore, a ready .gitignore, version-controlling just your theme or plugin, and deploy options.

How to Use .gitignore (with Examples)

A practical guide to .gitignore: pattern syntax, per-repo vs global ignore, ready-made templates, and the gotcha that trips everyone up - already-tracked files keep showing up.

How to Undo the Last Git Commit

Undo your last Git commit without losing work. When to use amend, reset --soft, reset --mixed, reset --hard, and revert, plus the rule for commits you already pushed.