Git Stash
Park incomplete changes, switch context without losing work, and know when a second worktree is clearer than a stash.
Context switching is a state-management problem
Choose commit, stash, or worktree
Commit
Use a branch commit when the state is meaningful, should survive normal cleanup, deserves a message, or must be shared and reviewed.
Stash
Use a named stash for a short interruption when the current changes are not yet a useful commit and only one working context needs to stay open.
Worktree
Use a linked worktree when two branches both need active files, tools, tests, or long-running context in separate directories.
Discard
Only restore unwanted content after inspecting its exact diff. Neither stash nor worktree is a reason to preserve known disposable noise.
What a stash stores
A stash entry is commit-based repository data representing working-tree and index state relative to a base commit. The friendly stack names—such as stash@{0}—are references used to find those objects. After a normal stash, tracked files are restored toward HEAD so you can switch context.
Tracked staged and unstaged work
git stash push captures tracked index and working-tree changes. It does not include ordinary untracked files by default.
Untracked or ignored content
-u includes untracked paths. -a also includes ignored paths and can capture large or sensitive content, so use it rarely and deliberately.
The base commit matters. Applying the entry later asks Git to place those recorded changes onto a possibly different current tree. The longer histories diverge, the more context and conflict risk grows.
Create a named, reviewed stash
git status --short
git diff
git diff --cached
# Stash tracked staged and unstaged changes with a useful label
git stash push -m "wip: validate checkout address"
# Include untracked files only after inspecting them
git stash push -u -m "wip: checkout form and fixture"
git status --short
git stash listINSPECTClassify every pathKnow what is tracked, staged, unstaged, untracked, ignored, generated, or sensitive.
NAMERecord why work pausedA message such as
wip: validate checkout addressis searchable and more useful than the default branch summary.VERIFYCheck both destinationsConfirm the working tree now has the expected state and the new stash appears at the intended stack position.
SWITCHBegin the interruption cleanlyOnly change branches after status proves no wanted path was left behind accidentally.
Test what you learned
Type the command that stashes tracked and untracked work with the label wip: checkout form.
Control stash scope deliberately
# Stash only selected paths
git stash push -m "wip: checkout UI" -- src/checkout/ tests/checkout.test.js
# Keep staged changes in place and stash other tracked edits
git stash push --keep-index -m "wip: unrelated unstaged edits"
# Interactively choose patch hunks
git stash push --patch -m "wip: selected checkout hunks"Pathspecs and patch mode can isolate coherent work, but partial state requires careful verification. Run all three views—status, plain diff, and cached diff—afterward. --keep-index is useful when staged content is ready for testing or committing while unrelated tracked edits need to move aside.
Inspect before restoring
git stash list
git stash show --stat stash@{0}
git stash show --patch stash@{0}
# Apply without deleting the stash entry
git stash apply stash@{0}
# After verification, delete the exact entry
git stash drop stash@{0}Recover, then verify
git stash apply leaves the entry in the stash list. Use this when context changed or the recovery deserves testing before deletion.
Apply, then drop on success
git stash pop is convenient for a routine recovery, but combining actions gives you less time to inspect the retained copy.
Always name the exact entry. Stack positions change when entries are added or dropped. Re-run git stash list immediately before using a stash@{n} selector, and prefer the entry’s message and patch over memory.
Test what you learned
Type the command that previews the complete patch stored in stash@{2}.
Resolve stash conflicts without losing the source
Applying a stash can conflict because the current branch changed the same context. Git writes conflict markers and leaves the working tree for resolution. The stash entry remains available when application does not complete cleanly.
git stash apply stash@{0}
git status
# Resolve each file to the intended current result, then:
git add path/to/resolved-file
git diff --cached
# Commit when the recovered unit is coherent:
git commit -m "Resume checkout validation"
# Drop only after proving the recovered commit contains the wanted work:
git stash drop stash@{0}Recover old work on its original base
When an entry is old and the current branch has diverged, git stash branch can create a new branch at the stash’s original base commit, check it out, and apply the stash there.
git stash list
git stash show --patch stash@{1}
git stash branch recover/checkout-wip stash@{1}This often reduces conflicts because the recorded changes return to the history they began from. On successful application, Git drops the stash entry, so verify the new branch, status, and diff immediately.
A linked worktree is another active checkout
git worktree lets one repository support multiple working directories. Linked worktrees share the object database and most refs, but each has its own working files, index, and HEAD. A commit created in one worktree is immediately available as an object and branch update to the others.
Objects and refs
- Commit, tree, and blob objects.
- Ordinary local branch refs.
- Remote-tracking refs and tags.
- Repository configuration in common storage.
Checkout state
- Working directory files.
- The index or staging area.
- HEAD and current checkout.
- Per-worktree administrative state.
Create a parallel branch workspace
# From the main repository, create a new branch and linked worktree
git worktree add -b hotfix/checkout ../shop-hotfix main
git worktree list
# Work inside the new directory
cd ../shop-hotfix
git status
# After committing, merging as appropriate, and cleaning the worktree:
cd ../shop
git worktree remove ../shop-hotfix
git worktree listThe example creates hotfix/checkout from main and checks it out in a sibling directory. Choose a path outside the main worktree so build tools and recursive searches do not accidentally treat one checkout as content inside the other.
git worktree add PATH BRANCH
Check out an existing branch in a new linked directory when that branch is not already checked out.
git worktree add -b NEW PATH START
Create NEW from START and check it out at PATH in one explicit operation.
git worktree list
Show registered worktree paths, current commit IDs, branches, and special states.
git worktree remove PATH
Remove a clean linked worktree and its administrative registration. It does not delete the branch.
Manage the full worktree lifecycle
- 01Create from a named base
Use an explicit starting revision and branch name so the new context is reproducible.
- 02Install and run independently
Each checkout may need its own generated dependencies, environment setup, development server, and ports.
- 03Commit on the correct branch
Check
git branch --show-currentand status inside that worktree before every commit. - 04Integrate deliberately
Merge, rebase, or review according to the project workflow; shared objects do not mean branches merge automatically.
- 05Remove only when clean
Prove wanted work is committed or preserved, remove the linked directory through Git, then delete the branch only if its lifecycle is complete.
If a worktree directory was removed manually or became unavailable, git worktree prune --dry-run previews stale administrative entries and git worktree prune removes eligible records. Preview before cleanup.
Match the tool to the interruption
Five-minute branch check
A named stash may be sufficient if all paths are understood and the original context can pause briefly.
Production hotfix during a feature
A sibling worktree keeps the feature files and tools intact while the hotfix receives a clean branch context.
Useful work at end of day
Create a coherent branch commit. Durable progress should not live indefinitely in a local stash stack.
Two versions under test
Use separate worktrees so both checkouts, dependency trees, and test processes remain visible.
Secret or generated file appeared
Classify and secure it. Do not use stash as a hidden storage location for credentials or ignored bulk output.
Unwanted experimental edits
Inspect the diff and restore only confirmed disposable changes instead of accumulating an unexplained stash.
Guided practice: interrupt and resume safely
Use a disposable repository with two tracked source files and one committed baseline. Create a feature branch and begin an unfinished change.
- 01Build mixed state
Stage one source edit, leave another unstaged, and create one reviewed untracked fixture.
- 02Create a named stash
Include the fixture explicitly, then prove the expected clean state and inspect the stored patch.
- 03Make an interruption commit
Switch branches, create a small unrelated fix, and commit it coherently.
- 04Resume with apply
Return to the feature branch, apply the exact stash without dropping it, and verify all three original states.
- 05Preserve and clean up
Commit the recovered feature, prove its contents, then drop only the verified stash entry.
Independent lab: handle a hotfix in parallel
Create a disposable repository with a main branch and an unfinished feature branch. Keep meaningful uncommitted feature work visible in the original directory while completing a simulated hotfix:
- Record the feature work’s status and both diffs.
- Create a sibling worktree and new hotfix branch from main.
- Prove each directory has a different branch, HEAD, index, and working state.
- Commit and test the hotfix in the linked worktree without altering feature files.
- Make the hotfix commit visible in the original worktree’s graph.
- Integrate the hotfix using the course’s current branch policy.
- Verify the hotfix worktree is clean, remove it through Git, and prove the branch remains available.
- Resume the untouched feature context and explain why a worktree was clearer than stashing it.
Common context-switching mistakes
Using anonymous stashes
Default labels become indistinguishable. Add a reason and inspect the exact entry before applying it.
Assuming untracked means included
Default stash omits untracked files. Classify them and use -u only when intended.
Popping without inspection
Apply first when recovery is uncertain, then drop only after tests and commit evidence preserve the work.
Keeping long-term work in stash
Stashes are local and easy to forget. Promote durable work to a named branch and coherent commits.
Deleting worktree directories manually
Use Git’s remove command so filesystem and administrative records stay synchronized.
Forcing removal of dirty worktrees
Force bypasses protection. Preserve or deliberately discard every path before removal.
Lesson review
You can now pause work without turning the repository into an unexplained pile of state. Named stashes support brief, inspected interruptions; linked worktrees support simultaneous branches with independent checkout state; coherent commits remain the durable record.
- I inspect tracked, staged, unstaged, untracked, and ignored paths before stashing.
- I name and inspect the exact stash entry rather than relying on stack position from memory.
- I use apply before drop when recovery needs verification.
- I understand which repository data worktrees share and which checkout state remains separate.
- I remove worktrees only after clean status and preservation evidence.