All tutorials

Tutorial 4 of 8

Stash: Park Your Half-Done Work

Switch tasks without committing messy work, then bring that work back when you are ready.

About 5 minutes

What you will be able to do

  1. Save uncommitted changes with git stash and see them with git stash list.
  2. Bring changes back with git stash pop or git stash apply, and know the difference.
  3. Include untracked files with -u, and handle a pop that stops with a conflict.

Title

Stash. Park half-done work, switch tasks, come back later.

This tutorial shows how git stash puts unfinished changes aside so you can switch to something urgent.

The situation

You are halfway through a feature. A teammate needs an urgent fix on main. Your work is not ready to commit.

Half-done changes make switching branches messy, because Git either carries them along or stops you.

Analogy: a drawer for unfinished work

git stash puts your unfinished changes in a drawer and gives you a clean desk.

git stash saves your tracked changes to a special stash entry and resets your folder to the last commit.

The analogy, and where it breaks

Putting half-done papers in a drawer clears your desk, and you can take them out later.

A real drawer takes any paper you drop in, but plain git stash leaves brand-new untracked files on your desk unless you add -u.

Stash, fix, come back

Stash, switch, fix, commit, switch back, pop.

git stash
git switch main
# fix the bug, then git add and git commit
git switch feature
git stash pop

The stash lets you make the urgent fix on a clean main and then continue your feature exactly where you left it.

The stash is a stack

Each new stash goes on top. The newest is always stash@{0}. Add -m to label it.

git stash push -m "login form halfway"
git stash list

Stash entries form a stack, so stash@{0} is always the most recent one, and a message makes each entry easier to recognise.

The analogy, and where it breaks

The drawer holds a stack of trays, and the newest tray is always on top.

Tray labels in a real drawer never change, but stash numbers shift: when you pop stash@{0}, the old stash@{1} becomes stash@{0}.

pop or apply

pop brings changes back and removes the entry. apply brings them back and keeps the entry.

git stash pop                # newest entry, then remove it
git stash apply stash@{1}    # a chosen entry, keep it
git stash drop stash@{1}     # remove an entry you no longer need

Use pop for the usual case, and use apply when you want to keep the entry, for example to use it on another branch too.

New files need -u

Brand-new files that Git has never tracked stay behind. Use git stash -u to include them.

git status --short
#  M form.js
# ?? notes.txt
git stash -u
git status --short
# (nothing listed: clean)

By default git stash ignores untracked files, so add -u when your half-done work includes new files.

The analogy, and where it breaks

Back to the drawer: you expect everything on the desk to go in.

Git only sweeps up files it already tracks, so untracked files need -u (--include-untracked) to go in the drawer.

When pop hits a conflict

If pop hits a conflict, Git keeps the stash entry. Fix the file, then drop the entry yourself.

git stash pop
# CONFLICT (content): Merge conflict in form.js
# The stash entry is kept in case you need it again.

# edit form.js and remove the conflict markers, then:
git add form.js
git stash drop

When a pop conflicts, Git applies what it can, keeps the stash entry as a backup, and waits for you to resolve and drop it.

The analogy, and where it breaks

Taking papers out of the drawer usually leaves it empty.

A failed pop leaves the entry in the stash, so your work is safe, but you must drop it yourself after fixing the conflict.

Stash or commit?

Stash is for short breaks. For work you want to keep for days, commit it on a branch instead.

Stashes are handy for quick switches, but commits on a branch are clearer and safer for longer pauses.

Recap

stash parks changes. list shows the stack. pop restores and removes. apply restores and keeps. -u includes new files.

git stash push -m "first"
git stash push -m "second"
git stash list

You can now pause and resume work safely, and next you will connect your repository to a remote.

Check yourself

0 of 4 answered

Check 1 of 4

What does git stash pop do when there is no conflict?

Check 2 of 4

Which line is printed first?

git stash push -m "first"
git stash push -m "second"
git stash list

Check 3 of 4

You edited app.js (tracked) and created notes.txt (never added). You run git stash. What is left in your folder?

Check 4 of 4

git stash pop reports a merge conflict. What happened to the stash entry?

mkdir -p ~/git-practice/t04-stash && cd ~/git-practice/t04-stash
git init -b main
echo "line 1" > app.txt && git add app.txt && git commit -m "Add app"

# Half-done work: one tracked change, one new file
echo "half-done work" >> app.txt
echo "scratch idea" > notes.txt

git stash
git status --short          # notes.txt is still here (untracked)
git stash pop

git stash -u -m "wip with notes"
git status --short          # nothing listed: the folder is clean
git stash list
git stash pop

# Make a conflict on purpose
git stash                   # stashes the app.txt change
echo "urgent fix" >> app.txt && git add app.txt && git commit -m "Urgent fix"
git stash pop               # CONFLICT: the entry is kept
git stash list              # still shows stash@{0}

# Open app.txt in an editor. Keep both lines you want and delete the
# marker lines that start with <<<<<<<, ======= and >>>>>>>. Then:
git add app.txt
git stash drop
git stash list              # empty now