Stash Work and Recover It

Learn how to stash work in progress and recover it with hands-on steps in this Git tutorial.

Focus: stash work in progress and recover it

Sponsored

You're mid-refactor on a feature branch, and the code is a mess — half-edited files, a broken test, and a teammate just asked you to urgently fix a bug on main. You cannot commit this broken work, but you also can't lose it. Do you copy files to a temp folder? Email yourself a patch? There's a better way. Git's stash lets you set aside work in progress in seconds, clean your working directory, and recover it whenever you're ready — without a single commit. In this lesson, you'll learn how to stash work in progress and recover it safely, avoid the common pitfalls, and integrate this tool into your daily Git workflow.

The problem this lesson solves

Every developer hits the same wall: you're deep in a feature, you've modified five files, and suddenly you need to switch branches — but your working directory is dirty. If you git checkout to another branch, Git may refuse because it would overwrite your uncommitted changes, or worse, it might let you switch and carry the changes into the wrong branch.

The core pain: You can't commit work that isn't finished and tested, but you can't just throw it away. Copying files manually is error-prone and slow. Stash solves this by giving you a safe, fast way to shelf your changes and restore them exactly as they were.

This is not a rare scenario. It happens during hotfixes, when you need to pull the latest changes, when you want to test a clean state, or when you switch between tasks. Stash work in progress and recover it is a core Git skill that separates beginners from confident practitioners.

By the end of this lesson, you'll be able to: - Explain why stashing beats committing or copying files in these situations. - Safely stash, list, apply, and pop changes. - Recover accidentally popped stashes. - Choose between stash and other Git features like commits or worktrees.

Core concept / mental model

Think of Git stash as a safety drawer for your changes. When you stash, Git takes your modified tracked files (and optionally staged and untracked files) and stores them in a stack-like structure called the stash. It then resets your working directory to the last commit — clean and tidy. Later, you can pull the changes out of the drawer and put them back onto your working directory.

Key ideas to internalize:

  • Stash is not a commit. It lives in a separate area (.git/refs/stash) and doesn't become part of your branch history.
  • Stash is stack-based. Each stash push adds a new entry on top. You apply or pop from the top by default.
  • Stash preserves your changes with metadata. Each stash entry records the commit it was based on, so you can reason about which changes belong to which state.
  • Stash can include untracked files if you ask it to (with -u), but by default it only stashes tracked changes.
  • Recovering is two-way: apply leaves the stash in the stack; pop applies and removes it. If you lose a stash, there are ways to recover it (ref logs!)

Here's a visual in words:

Before stash: Working dir = messy (5 changed files)
    |
    v
git stash push
    |
    v
Working dir = clean (like last commit) + stash stack has entry #0
    |
    v
git stash pop
    |
    v
Working dir = messy again (5 changed files) + stash entry #0 gone (if pop)

How it works step by step

Let's walk through the typical workflow logically, from start to finish. Visualize each step as a cause-and-effect relationship.

Step 1: Check your dirty state

Before you stash, check what's changed:

git status

This shows modified tracked files, staged files, and untracked files. You need to know what will and won't be included in the stash.

Step 2: Stash your changes

Run the basic stash command:

git stash push -m "WIP: refactor auth"

A short message helps you identify the stash later. If you don't provide a message, Git uses the latest commit message. By default, only tracked and staged changes are stashed. Untracked files are ignored.

Step 3: Verify the stash and clean state

git stash list
git status

git stash list shows entries like stash@{0}: On branch: WIP: refactor auth. Your working directory is now clean (except for untracked files).

Step 4: Switch branches or do your urgent work

Now you can safely switch branches, pull, make the hotfix, commit it, and switch back.

Step 5: Recover your stashed work

When you're ready to pick up where you left off, you have two options:

  • git stash pop — applies the stash and removes it from the stack.
  • git stash apply — applies the stash but keeps it in the stack (useful if you want to apply it to multiple branches).

Both default to the most recent stash (stash@{0}). You can specify any stash using its ID.

Step 6: Resolve conflicts (if any)

When you pop or apply onto a branch that has diverged, Git may hit conflicts. You'll need to resolve them just like a merge conflict, then git add the resolved files. The stash remains in the stack until you clear it — so after resolving, it's wise to pop again to drop it if you're done.

Hands-on walkthrough

Let's put this into practice with a concrete example. We'll create a repo, make changes, stash them, switch branches, fix something, then recover and continue.

Set up the playground

mkdir stash-demo && cd stash-demo
git init
git config user.email "demo@example.com"
git config user.name "Demo"
echo "Hello" > app.py
git add app.py
git commit -m "Initial commit"
# Now modify the file (uncommitted)
echo "Hello, world!" >> app.py

Now we have a working directory with one modified file. Let's verify:

git status

Expected output:

On branch master
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:   app.py

Stash the change

git stash push -m "WIP: add greeting"

Now check the state:

git stash list
git status

Expected output:

stash@{0}: On master: WIP: add greeting
On branch master
nothing to commit, working tree clean

Do urgent work on another branch

git checkout -b hotfix
# fix a typo in app.py? No, let's create a new file
echo "Fix" > fix.txt
git add fix.txt
git commit -m "Hotfix"
git checkout master

Recover the stash

Now come back to master and pop:

git stash pop

Expected output (similar):

On branch master
Changes not staged for commit:
    modified:   app.py

no changes to commit
Dropped refs/stash@{0} (abcdef1234567890123456789012345678901234)

Your change is back, and the stash entry is gone. Verify with git stash list — it should be empty.

Pro tip: If you want to apply the same changes to multiple branches, use git stash apply instead of pop, then pop only when you're finally done. This is handy when you're carrying a WIP across feature branches.

More advanced: including untracked files

By default, untracked files are left alone. To include them in the stash:

echo "new feature" > new_feature.py
git stash push -u -m "WIP with untracked"

Now the untracked file is stashed too. git stash pop restores it.

Compare options / when to choose what

You're not forced to stash — Git offers other ways to handle WIP. Here's a comparison to help you choose.

Approach When to use Pros Cons
git stash Quick switch, temporary shelf Instant, reversible, no commit pollution Not ideal for long-lived WIP; only one default stack
Create a WIP commit (possibly on a branch) Work that will live for days/weeks Keeps history, can share with others Pollutes history; you must reset later
git worktree You need to work on two branches simultaneously Clean isolation, no stash needed Heavier setup; separate directories
Copy files manually Extremely small changes Simple, no Git knowledge Error-prone, loses merge context

Decision guide: - Temporary (minutes to a few hours): stash is your friend. - Ongoing feature (days): create a dedicated branch and commit incrementally (even if messy) — it's easier to manage. - Need to switch contexts repeatedly: worktrees shine, as you don't have to stash at all. - Never copy files manually if you can avoid it.

Variations to consider: - git stash branch <branch> <stash>: creates a new branch from the stash's original commit and applies the stash there. Great when you realise you were on the wrong branch. - git stash show -p stash@{0}: preview the changes in a stash without applying it. - Use git stash push -- <file> to stash only specific files.

Troubleshooting & edge cases

You'll hit a few snags when stashing. Here's how to diagnose and fix the most common ones.

Problem 1: git stash pop results in conflicts

Symptom: conflicts appear in files; Git reports merge conflict markers (<<<<<<<).

Cause: The working branch has changed since you stashed — e.g., you committed other changes to the same lines.

Fix: Resolve each conflicting file like a merge. Then git add the resolved files. The stash still exists because the pop failed; fix, add, then git stash drop to remove it.

Problem 2: You popped a stash by accident and now it's gone

Symptom: git stash list is empty, but your changes are as expected in the working directory — you actually wanted to apply without dropping.

Cause: You used pop when you meant to use apply.

Fix: The stash is not lost forever! You can recover it using the reflog:

git fsck --unreachable | grep commit
git reflog show --all | grep stash

Then use the commit hash to create a new stash:

git stash apply <hash>

Pro tip: Don't panic. Git's reflog keeps a record of everything for 30 days by default. You can almost always recover a popped stash.

Problem 3: Untracked files missing after stash

Symptom: After popping, one of your new files is missing.

Cause: You stashed without -u, so untracked files were never included. They remained in the working directory (not stashed) — but if you then switched branches, the file might have stayed or been overwritten.

Fix: Always use -u if you have untracked files you want to shelf. Check where your file went with git status. If it's gone, check the stash's git stash show -p to see if it's inside a stash entry.

Problem 4: You stashed more than you meant to

Symptom: You stashed staged and unstaged changes, but you only meant to stash unstaged changes.

Cause: git stash push stashes both by default.

Fix: Use -- <pathspec> to limit what you stash. Or, if you want to keep staged changes, use git stash push --keep-index to stash only unstaged changes.

Problem 5: git stash pop says "Could not restore untracked files"

Symptom: The stash includes untracked files, but there's a file with the same name in the working directory.

Cause: A conflict between the stashed untracked file and a new file.

Fix: Either delete or rename the conflicting file in your working directory, then pop again.

What you learned & what's next

You now have the git stash superpower. Let's recap what you achieved in this lesson:

  • You can stash work in progress with git stash push and a descriptive message.
  • You can list your stash stack with git stash list and inspect a stash's contents.
  • You can recover it with git stash pop (apply and drop) or git stash apply (keep it).
  • You know how to handle untracked files with -u and how to stash only specific files.
  • You can troubleshoot conflicts, accidental pops, and missing files using Git's safety nets like reflog.
  • You know when to choose stash over commits or worktrees.

That covers every learning objective from the brief: you can explain the core idea behind stashing and you've completed a practical exercise.

What's next? In the next lesson, you'll look at cleaning your working tree with git clean — the perfect companion to stash for keeping your repo tidy. You'll learn how to remove untracked files and directories safely, and how to combine git clean with stash to prepare a pristine state for the next merge or branch switch.

Keep practicing stash until it feels natural — your future self will thank you every time you have to drop everything and fix an emergency.

Practice recap

Create a new repo, add a file, then edit it. Practice git stash push -m "test", check git stash list, then git stash pop. Repeat with an untracked file using -u. For a bonus, try git stash apply twice to see how to reuse the same stash.

Common mistakes

  • Using git stash pop when you meant to keep the stash for later—prefer apply if you need to reuse the change across branches.
  • Forgetting -u when you have untracked files, leading to those files not being stashed (and possibly lost if you switch branches).
  • Assuming stash is a substitute for commits—if WIP will last for days, a branch + commit is cleaner and easier to track.
  • Accidentally popping the wrong stash by not specifying an index (e.g., git stash pop stash@{1}).

Variations

  1. Use git stash push -- <file> to stash only selected files instead of everything.
  2. Use git stash branch <branch> <stash> to recover a stash and create a branch at the right commit in one step.
  3. Consider git worktree instead of stash when you need to work on two branches simultaneously without ever dirtying your main working directory.

Real-world use cases

  • A developer must drop a mid-refactor to patch a production bug; stash shelves the WIP in seconds, allowing a clean branch switch and hotfix commit.
  • A team uses git stash push -u to temporarily move untracked config files aside when switching between feature branches with different environments.
  • A developer accidentally pops a stash and loses it, then recovers it via git reflog before reapplying—saving hours of rework.

Key takeaways

  • git stash safely shelves uncommitted changes (tracked + staged by default) and gives you a clean working directory.
  • git stash pop applies the top stash and removes it; git stash apply applies without dropping—use each intentionally.
  • Including untracked files requires -u; otherwise they stay behind and could be overlooked.
  • You can stash specific files with git stash push -- <paths>—great for partial WIP.
  • Lost stashes are recoverable via the reflog and git fsck, so don't panic when you accidentally pop.
  • Resolve pop conflicts like merge conflicts, then drop the stash only after you've verified the result.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.