Stash: parking work
Beginner Git CLI VS Code UI IntelliJ UI
Why this matters
You are in the middle of an edit when something else needs doing now: a colleague asks you to check main, a pull is needed, a quick fix on another branch. Your edits are not ready to commit, and Git refuses to switch or pull over uncommitted changes that would be overwritten. Stash is the drawer you put them in.
When Git refuses
$ git switch feature/21-difficulty-filtererror: Your local changes to the following files would be overwritten by checkout:
README.md
Please commit your changes or stash them before you switch branches.
Abortinggit pull prints a similar message (…would be overwritten by merge) when incoming commits touch a file you edited. Git is protecting your uncommitted work; it names the two exits, and this lesson is the second one.
Stash and pop
$ git status -s M docs/getting-started.md
?? docs/draft.md$ git stashSaved working directory and index state WIP on main: dc9a369 Revert "feat: add Coast Walk trail and FAQ entry (#29)"$ git status -s?? docs/draft.mdThe modified file is back to its committed state, and its edit is stored in the stash. Note what stayed: the untracked docs/draft.md. By default stash takes tracked changes only; git stash -u includes untracked files too.
Now switch, pull, fix, whatever you needed. Then bring the work back:
$ git stash popOn branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: docs/getting-started.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
docs/draft.md
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (7931fe9e3bac7f7e0619f0e66acc345c9c40bc2d)pop restores the changes and removes the stash entry. git stash apply restores and keeps the entry, useful if you want the same changes on two branches.
Several stashes, with names
$ git stash push -u -m "getting-started notes"Saved working directory and index state On main: getting-started notes$ git stash liststash@{0}: On main: getting-started notesStashes stack: the newest is stash@{0}, the previous becomes stash@{1}. git stash show summarizes the newest (git stash show stash@{1} another; -p for the full diff), git stash pop stash@{1} restores a specific one, and git stash drop deletes one without restoring:
$ git stash show docs/getting-started.md | 2 ++
1 file changed, 2 insertions(+)Always name a stash you might keep for more than an hour; "WIP on main" tells you nothing tomorrow.
Stash or branch?
A stash is for minutes or hours. For anything longer, commit on a branch: commits are visible in the log, can be pushed and reviewed, and never surprise you three weeks later as stash@{4}. A good rule: if you would want to describe the work to a colleague, it is a branch; if it is "the two lines I was typing when the phone rang", it is a stash.
In the tools
Everything above. Stashes are local: they never push, and they are not backed up. A pop that meets a conflict leaves the stash in place; resolve the file, then git stash drop.
- Source Control → … menu → Stash → Stash (or Stash (Include Untracked)). VS Code asks for a message; give one.
- To restore: … → Stash → Pop Latest Stash, or Pop Stash… to pick one; Apply variants keep the entry.
- The Source Control Graph and the Stashes section (with GitLens) list existing stashes.
IntelliJ offers two tools. Git → Uncommitted Changes → Stash Changes… is Git's stash (name it in the dialog); Unstash Changes… lists and restores them. IntelliJ's own Shelve (right-click changes → Shelve Changes) does the same job with a nicer UI and works even outside Git, but shelves are IntelliJ-private and invisible to git stash list. Either is fine; pick one and know which you used. When switching branches with uncommitted changes, IntelliJ offers to shelve them automatically ("Smart checkout").
Not applicable: stashes live in your local repository and never reach the server.
Not applicable either. If you use github.dev, its Source Control panel offers the same Stash commands as VS Code, stored in the browser session.
Common mistakes
- Stashing, switching branches, and popping on the wrong branch. The changes apply wherever you pop. Check
git status(the branch line) beforepop. - Forgetting untracked files. They stay in the working tree and can be overwritten by a switch. Use
-uwhen a new file is part of the work. - A stash pile.
git stash listwith eight unnamed entries is unrecoverable knowledge. Name them, and clear them weekly. - Expecting stashes on another computer. They are local. Push a branch instead.
Try it yourself
Goal: stash, switch, return, pop.
- In the playground, edit
docs/getting-started.mdand createdocs/draft.md. - Run
git stash push -u -m "draft work", thengit status -s(clean) andgit stash list. - Do something else:
git log --oneline -3, or switch to another branch and back if you have one. - Run
git stash popandgit status -s.
Expected result: after step 2 the tree is clean and the list shows one named stash; after step 4 both the edit and the new file are back and the list is empty.
Show solution
-u is what brought docs/draft.md along; without it the file would have stayed untracked in the working tree throughout. pop restored both and dropped the entry. Clean up with git restore docs/getting-started.md && rm docs/draft.md.