One of the biggest promises of AI is helping developers work on multiple tasks at once. Whether you're debugging a mobile app, reviewing a pull request, writing documentation, or experimenting with a new feature, AI can reduce the mental overhead of context switching.
But long before AI became part of our daily workflow, developers relied on a much older multitasking technique: Git Stash.
Imagine you're halfway through a feature when an urgent bug report arrives. You need to switch branches immediately, but your current work isn't ready to commit; half the functions are stubs, the tests are failing, and committing it would pollute your history. Traditionally, the solution was to shelve your work with Git Stash, deal with the fire, and come back later.
This article walks through Git Stash from the basics to the advanced recovery tricks most developers never learn, then looks at how AI changes the multitasking equation.
Why This Matters Beyond the Code
An interruption is expensive because of what happens in the developer's head. Picking up a complex task means holding a lot of context at once: what you were building, why, what you'd already tried, and what's next. An urgent interruption wipes that mental picture, and rebuilding it can take fifteen or twenty minutes after the interruption is over. Multiply that by a few interruptions a day across a whole team, and it turns into a real drag on how fast the company ships. So the tools and habits in this article are about protecting focus, which is what actually moves work out the door.
Stashing and Worktrees, in Plain English
Git stash and git worktree both solve the same basic problem: not losing your place when you have to stop what you're doing. Think of a developer's workspace like a desk. Stashing is sweeping your half-finished paperwork into a drawer so you can clear the desk for something urgent, then pulling those same papers back out later, exactly as you left them. A worktree is different: instead of clearing the desk, you set up a second desk in another room and work on two things at once without packing anything away. The rest of this article is really just two ideas dressed up as commands: stash to pause one task, and worktree to run two side-by-side.
What Is a Git Stash?
A Git stash is a temporary storage area where you can safely shelve your uncommitted changes without making a formal commit.
Running git stash takes the modified, tracked files in your working directory, saves them onto a local stack-like structure, and reverts your workspace back to its last clean commit state.
This lets you quickly switch tasks, change branches, investigate bugs, or pull updates without losing your current work. Later, when you're ready to continue, you can restore those changes exactly where you left off.
Think of Git stash as a developer's pause button: your work is safely stored away, your workspace is cleaner, and you can return to it whenever you need.
What's Actually Happening Under the Hood
It helps to understand that a stash is just a commit (or a few). When you stash, Git creates commit objects that record the state of your working directory and index, then points the refs/stash reference at them. The stash list is effectively a stack of these hidden commits.
This matters for two reasons:
- Because stashes are real commits, they can be inspected, diffed, and even recovered after deletion (more on that later).
- Because they live in
refs/stashand not on any branch, they don't show up in your normal history and won't be pushed to a remote.
You can prove this to yourself:
git stash
git log -g refs/stash # the stash reflog, showing each stash as a commit
A note on syntax: Older tutorials use git stash save "message". That form is now obsolete. The modern, recommended command is git stash push, which is more flexible (it accepts pathspecs, patch mode, and more). All the examples below use push.
Heads up: From here on, this gets more hands-on: the actual commands you'll use day to day.
Creating Stashes
The Basic Stash
git stash
This stashes tracked, modified files and resets your working tree to the last commit.
Include Untracked Files
By default, Git only stashes tracked files. Brand-new files Git hasn't seen yet are left behind, which can be a surprising trap. To include them:
git stash -u
# or the long form
git stash --include-untracked
Include Ignored Files Too
If you also need to stash files matched by .gitignore (build artifacts, local config, etc.), use:
git stash -a
# or
git stash --all
Use this sparingly. It can sweep up large node_modules or dist folders if they're gitignored.
Give Your Stashes Meaningful Names
When you're juggling several tasks, unnamed stashes become a guessing game. Always add a description:
git stash push -m "refactor pipeline config handling"
Now stash@{0} will tell you exactly what it contains a week from now.
Stash Only Specific Files
You don't have to stash everything. Pass a pathspec to stash just the files you name:
git stash push -m "wip on auth service" -- src/auth/ tests/auth.test.js
Everything else stays in your working directory. This is invaluable when one file is ready to keep working on but another is in a broken state you'd rather set aside.
Interactively Choose What To Stash (Patch Mode)
Sometimes a single file contains two unrelated changes, and you only want to stash one of them. Patch mode walks you through each change (hunk) and asks whether to stash it:
git stash push -p -m "experimental logging only"
For each hunk Git prompts you with options like y (stash this hunk), n (keep it), s (split into smaller hunks), and q (quit). This gives you surgical control over what gets shelved.
Stash, But Keep Your Staged Changes
A common workflow: you've staged exactly what you want to commit, and you want to run your tests against only that staged state, without the noise of your unstaged work. --keep-index stashes everything but leaves your staged changes in the working tree:
git add .
git stash --keep-index
npm test # tests run against only what you staged
git stash pop # restore the rest
Stash Only What's Staged
Since Git 2.35 you can stash only the staged changes and leave unstaged work untouched:
git stash push --staged -m "the part that's ready to set aside"
Inspecting Stashes
List Your Stashes
git stash list
Example output:
stash@{0}: On main: refactor pipeline config handling
stash@{1}: On feature/login: fix oauth callback
The number in braces is the stash's position on the stack; stash@{0} is always the most recent.
Inspect Before Restoring
Before applying a stash, review what it contains so you don't restore the wrong set of changes.
Summary of changed files:
git stash show stash@{0}
Full diff:
git stash show -p stash@{0}
If you stashed untracked files and want them included in the diff (Git 2.32+):
git stash show -p --include-untracked stash@{0}
Restoring Your Work
Apply and Remove the Stash
When you're ready to pick up where you left off:
git stash pop
This applies the most recent stash to your current branch and removes it from the stack.
Apply Without Deleting
If you might want to reuse the same stash, for example, applying the same work-in-progress to two different branches, use apply, which leaves the stash in place:
git stash apply stash@{1}
Handling Conflicts When Restoring
If the branch has moved on since you stashed, pop or apply may produce merge conflicts. Two things are worth knowing:
- On conflict,
git stash popdoes not drop the stash. Your safety net stays in the list until you've resolved everything and confirmed the result. - You resolve these conflicts exactly like a merge: edit the conflicted files,
git addthem, and then, becausepopdidn't drop the stash, clean up manually:
git stash pop
# ... resolve conflicts in your editor ...
git add resolved-file.js
git stash drop # remove the stash you just (manually) finished applying
Cleaning Up
Once a stash is no longer needed, remove it.
Delete the most recent stash:
git stash drop
Delete a specific stash:
git stash drop stash@{2}
Delete all stashes:
git stash clear
A clean stash list makes future multitasking far less confusing. Just be careful with clear. It's irreversible through normal commands (though see the recovery section below).
Converting a Stash into a Branch
One of the most underrated Git features is turning a stash into its own branch:
git stash branch pipeline-fix stash@{1}
Git will:
- Create a new branch from the commit where the stash was originally created.
- Apply the stash onto it.
- Drop the stash if the operation succeeds.
This is perfect for two situations: when a quick interruption grows into a real project worth its own branch, or when a stash won't apply cleanly to your current branch.
Recovering a "Lost" Stash
This is the trick that turns Git stash from useful into trustworthy. Because stashes are commits, dropping or clearing one doesn't immediately erase it: the commit becomes unreachable but lingers until Git's garbage collection runs (typically not for weeks).
If you dropped a stash by mistake, you can find the dangling commit:
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
Inspect each candidate to find your work:
git show <commit-sha>
Once you've identified it, restore it as if it were still a stash:
git stash apply <commit-sha>
Knowing this exists means you can use drop and clear without anxiety.
When Stash Isn't the Right Tool: Git Worktrees
Stash is great for brief interruptions. But if you frequently need to work on two branches at the same time (say, building a feature while a long review cycle drags on), constantly stashing and popping gets tedious and error-prone.
Git worktrees solve this differently. Instead of shelving your work, they give you a second working directory checked out to a different branch, both backed by the same repository:
git worktree add ../project-hotfix hotfix/login-bug
You now have two folders side by side. Your feature work stays untouched in your main directory, and the hotfix lives in ../project-hotfix. Open both in separate editor windows and switch by changing windows, not by stashing.
Manage them with:
git worktree list
git worktree remove ../project-hotfix
The rule of thumb: use stash for a quick "pause and come right back" interruption; use worktrees when two contexts need to stay alive in parallel for a while.
Why This Isn't Just a Developer Problem
The reason any of this matters has nothing to do with Git syntax. It's about how much time and focus get burned every time someone gets pulled off one task and dropped onto another. That cost shows up outside the terminal too. A PM re-explaining a feature's status after an interruption. A client noticing a task took three days instead of one. A handoff that goes sideways because the next person can't tell what was finished from what was just a placeholder. It's the same problem Git Stash solves for code, just further up the chain: protect the train of thought, and the team loses less time to interruptions.
Real-World Use Cases
A few scenarios where reaching for stash (or a worktree) pays off:
-
The urgent hotfix: You're mid-feature when production breaks.
git stash -u, switch to main, branch off, fix, ship, thengit stash popback into your feature. No throwaway "WIP" commit polluting history. -
Pulling with a dirty tree: You want the latest from
origin/mainbutgit pullrefuses because of local changes. Stash, pull, pop:git stash git pull --rebase git stash pop -
"Does this bug exist without my changes?": You suspect your work-in-progress introduced a bug. Stash it to get a clean baseline, reproduce (or fail to reproduce) the bug, then pop your changes back. A fast way to isolate cause from coincidence.
-
Started on the wrong branch: You started editing on main instead of a feature branch:
git stash git switch -c feature/correct-branch git stash pop -
Reviewing a colleague's PR: To run someone's branch locally without losing your work, stash, check out their branch, test it, then return and pop.
-
Splitting tangled work: You've accidentally bundled two features in one working tree. Use patch-mode stashing (
git stash push -p) to peel off one feature at a time and commit them separately.
How AI Changes the Game
Git stash preserves code. However, it can't preserve what actually costs you time after an interruption: the mental state of why you were making a change, what you'd already tried, and what you intended to do next. You come back to a clean diff and spend twenty minutes remembering what to do.
Scaling the impact: These minutes add up fast across a team. When context survives an interruption, people spend less time decoding half-finished work and more time actually shipping. It's easier to run several workstreams at once without anyone losing their mental model, and the intent behind a change stays attached to it, not just the diff. Multiply that across a team, and preserving context stops being personal housekeeping. It's a real lever for shipping faster and with fewer mistakes.
This is where AI assistants add a genuinely new layer. They can preserve and reconstruct context, not just changes:
- Summarize unfinished work before you stash: Ask the assistant to read your diff and write a few sentences on what the change does and what's left to do. Paste that into your stash message or a scratch note.
- Generate the stash message itself: Instead of
git stash push -m "stuff", have the assistant draft a descriptive message from the actual diff. - Reconstruct context when you return: Days later, feed the diff back and ask "what was I doing here and what's the obvious next step?" far faster than re-reading every line cold.
- Explain prior decisions: When picking up old work, ask the assistant to explain why a particular approach was likely taken, or to flag anything that looks half-finished or risky.
- Review before you commit: Run a quick AI review of the staged diff to catch leftover debug logging, missing error handling, or a TODO you meant to resolve.
- Produce documentation in parallel: While you keep coding, the assistant can draft the docstring, README section, or changelog entry for the work you just finished.
A practical combined workflow looks like this:
# About to get interrupted. Generate a description of the WIP from the diff,
# then stash with that message.
git diff # review, or pass the diff to your AI assistant
git stash push -u -m "auth refactor: token validation done, refresh flow TODO"
# ... handle the interruption ...
# Coming back:
git stash show -p stash@{0} # see the code again
# ask the assistant to summarize the diff and suggest the next step
git stash pop
Git stash remains an essential multitasking tool, and worktrees extend it for parallel work. AI doesn't replace either. It complements them by preserving the reasoning behind the code, so returning to a task is about continuing rather than remembering.
The result is less time spent reconstructing where you left off and more time spent building.
Key Takeaways
-
Stash lets you pause unfinished work and pick it back up exactly where you left it, without committing broken code.
-
Worktrees are for running two branches side by side over time, not just pausing one task briefly.
-
Neither one keeps the reasoning behind the work, why you made a call, what's still left to do. That's the gap AI now fills.
-
Cleaner Git history is nice, but the real win is less time lost to interruptions and handoffs that hold up.
What Multitasking Is Really About
Multitasking has always been part of building software; the question is only what you lose each time you switch. Git gave us a way to protect the code: stash it, branch it, and come back to it clean. That solved half the problem. The other half was the reasoning: the half-formed plan and the reason you chose one approach over another. That used to live only in your head, and it evaporated the moment something urgent pulled you away.
For a team building a product, that shift is bigger than any single command. When both the code and the thinking behind it are preserved, switching tasks stops being a tax. Work moves in parallel without piling up half-finished work; people hand off to each other without losing the thread; and the team spends its energy on the product instead of on remembering where it was. That's the standard Designli holds for every team in TractionLab, where context is owned, handoffs are clean, and focus stays on shipping. The tools change, but the goal stays the same: protect focus, lose less to the switch, and keep building.




