Git and GitHubgit 2.54 · GitHub · macOS, Linux or Windows
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
26 small wins to finish your pathNext lesson →

Stashing work in progress

git stash takes the changes in your working tree off to one side and gives you a clean working tree back, so you can do something else and bring them back after.

Last updated: 12 Oct, 2026 · git 2.54

Amending, reverting and resetting a commit was about undoing work for good. A stash is the opposite: the work is fine, the moment is wrong.

What a stash does with work you are not ready to commit. A working tree holding half-finished edits is emptied by git stash, which takes the edits off the working tree and puts them on the stash stack, leaving a clean working tree that matches the last commit. The stash stack holds stash@{0}, the newest, above stash@{1}; it is local to this repository and a push never sends it. git stash pop puts stash@{0} back on the working tree and removes it from the stack, while git stash apply puts it back and keeps it. In between, you are free to switch branches, pull, or start something else.

Syntax: the whole of git stash in six lines.

bash
git stash                      # put the changes aside, clean the working tree
git stash push -m "a name"     # the same, with a label you will recognise
git stash list                 # what is on the stack
git stash show -p stash@{0}    # the changes in one entry, as a diff
git stash pop                  # put the newest back and remove it from the stack
git stash apply                # put it back and keep it on the stack

Setting up a repository to work in

The examples below all work in one throwaway repository: a folder with a single file, committed once. The two export lines stand in for the name and email you set once with git config --global, and fix the date so the commit hashes are the same on every run.

ExampleOne file, one commit: where every example below starts
export GIT_AUTHOR_NAME=Reader GIT_AUTHOR_EMAIL=reader@example.com GIT_AUTHOR_DATE=2026-10-12T10:00:00
export GIT_COMMITTER_NAME=Reader GIT_COMMITTER_EMAIL=reader@example.com GIT_COMMITTER_DATE=2026-10-12T10:00:00
mkdir ask-docs && cd ask-docs && git init -q -b main
printf 'chunk_size = 400\n' > settings.py
git add . && git commit -q -m "Add the settings"
git log --oneline

The problem a stash solves

Git will not switch branches when switching would overwrite a change you have not committed. This is the error that sends people looking for git stash, so here it is first. It needs a second branch with a commit of its own.

ExampleA branch that has moved on, and back to main
git switch -q -c experiment
printf 'chunk_size = 200\n' > settings.py
git commit -q -am "Try 200 character chunks"
git switch -q main
git branch

experiment has its own commit changing the same file, and the star says you are back on main. Now start an edit on main and try to leave.

ExampleGit refuses rather than throw the edit away
printf 'chunk_size = 400   # trying 600 next\n' > settings.py
git switch experiment

Git names the file it would have overwritten and tells you the two ways out: commit the change, or stash it. Committing half an idea on the wrong branch is how histories become hard to read, so for a change you want to keep but not record, the stash is the answer.

Putting the work aside and taking it back

git stash saves the change, resets the working tree to the last commit and pushes an entry on to a stack.

ExampleThe change off the working tree
git stash
git status --short
echo "(clean, so the switch works now)"

The message names the commit you were on, WIP on main followed by the last commit, which is how you tell two stashes apart when there is no label. The working tree is clean, so git has nothing to overwrite.

ExampleBoth switches run, and the entry waits
git switch experiment
git switch main
git stash list

This is what the stash was for: the branch was visited and the work is still there, on the stack, named stash@{0}.

ExampleThe change written back and taken off the stack
git stash pop
cat settings.py
git stash list
echo "(the stack is empty again)"
  • The edit is in the file again. cat shows the half-finished line, comment and all.
  • pop empties the stack. Git says it dropped the entry, and git stash list prints nothing.
  • git stash apply is the other half of the pair. It writes the change back and leaves the entry in place, which is what you want if you plan to put the same change on two branches.

Labelling and reading a stash

A stack of entries all called WIP on main is useless a day later. git stash push -m gives one a name.

ExampleTwo labelled entries on the stack
printf 'chunk_size = 200\n' > settings.py
git stash push -m "trying smaller chunks"
printf 'Answer only from the notes.\n' > prompt.txt
git add prompt.txt && git stash push -m "a first draft of the prompt"
git stash list

The newest entry is stash@{0}, so every new stash pushes the others down and the numbers of old entries change as you add more. The second stash took prompt.txt even though it was staged: a stash saves the staging area too.

ExampleWhat is inside an entry, without putting it back
git stash show -p stash@{0}

show -p prints a diff. Here the entry holds a new file, so every line is a + line, and nothing was written to the working tree.

Untracked files, which a plain stash leaves behind

A stash saves tracked files. A file git has never seen is not in it, so a stash can leave your working tree looking dirty.

ExampleThe edit went, the new file stayed
printf 'chunk_size = 200\n' > settings.py
printf 'print("scratch")\n' > scratch.py        # new file, never added
git stash
git status --short

The stash took the edit to settings.py and left scratch.py, which git is not tracking, where it was.

Example-u takes the untracked ones too
git stash -u
git status --short
echo "(clean now)"
git stash list

The working tree is clean and the stack has two entries: the first stash and the one that took scratch.py. Files that are ignored by .gitignore are left alone by both; -a takes those as well, which is rarely what you want, since it sweeps up your virtual environment.

When a pop runs into a conflict

A stash is applied to whatever the working tree looks like now, which may not be what it looked like when you stashed. If the same lines have changed in between, the pop conflicts, exactly like a merge.

ExampleA stash made at 400, and a commit that moved the line to 800
printf 'chunk_size = 200\n' > settings.py
git stash push -m "trying smaller chunks"
printf 'chunk_size = 800\n' > settings.py
git commit -q -am "Raise the chunk size to 800"
git log --oneline

The stash holds 200. The committed file now says 800, and both changed the same line.

ExampleThe pop that cannot be applied cleanly
git stash pop

Git reports the conflict and says it kept the stash entry in case you need it again. The last line is the one that matters: a failed pop cannot lose the work.

ExampleThe markers in the file, the entry on the stack
cat settings.py
git stash list
  • The conflict is marked in the file. <<<<<<< Updated upstream is the committed line and >>>>>>> Stashed changes is the line from the stash. You edit the file to what you want and remove the markers.
  • The entry was not dropped. git stash list still shows it, so you can try again or look at it.
  • Remove it yourself when you are done. git stash drop takes the newest entry off the stack once you have finished with it.

Stash against a commit on a branch

git stashA commit on a throwaway branch
Where the work livesa stack in this repositorya real commit
Can you push it?no, a stash never leaves the machineyes
Does it have a message?only if you use -malways
Survives a fresh clone?noyes, once pushed
Good forminutes or hoursdays, or anything you would be sad to lose

Where a stash fits a working day

  • A bug report arrives mid-change. Stash, switch, fix, switch back, pop.
  • A pull you need before you are ready to commit. Stash, git pull, pop, and deal with any conflict in the file rather than in the history.
  • Seeing what a file looks like without your change. Stash it, run the project, then pop.
Watch out. A stash is local, has no branch and is easy to forget. Work stashed on Friday is invisible on Monday unless you run git stash list, and a stash is not pushed, so a lost machine takes it with it. Anything you would mind losing belongs in a commit on a branch, not on the stack.
Try it yourself
  • Make two stashes, then run git stash apply stash@{1} and git stash list. The entry is still there, which is the difference from pop.
  • Run git stash show -p with no argument. It shows the newest entry.
  • Stash a change, then run git log --oneline --all. The stash does not appear as a branch, which is why it is easy to lose track of.

Little by little, you're building something great.