Stash, Worktrees, Temporary Work, and Parallel Development Contexts: Guided Hands-On Workflow and Core Operations
Practice stash push/list/show/apply/pop/drop/branch and worktree add/list/lock/move/remove/prune in a disposable repository, including conflict recovery and parallel feature/review/hotfix contexts.
Learning objectives
- Create selected-path and staged-only stash entries and inspect exactly what they contain.
- Apply, pop, drop, and recover via stash branch while preserving evidence through a conflict.
- Create feature, detached-review, and hotfix worktrees attached to one repository.
- Observe branch checkout exclusivity and use worktree lock, move, remove, and prune safely.
- Verify branch associations and shared commit visibility before cleanup.
1. Build a disposable context-switching repository
The entire lab lives in a new disposable directory. It uses no remote account and no valuable repository.
Git Bash, Bash, or zsh
mkdir git-context-lab
cd git-context-lab
git init -b trunk main
cd main
git config user.name "Context Lab"
git config user.email "context-lab@example.invalid"
printf "mode=stable\nmetrics=false\n" > service.conf
printf "# Context Service\n" > README.md
printf "build/\n" > .gitignore
git add service.conf README.md .gitignore
git commit -m "Create context-switching baseline"
git status --short --branch
git stash list
git worktree list --porcelain
PowerShell setup alternative
New-Item -ItemType Directory git-context-lab | Out-Null
Set-Location git-context-lab
git init -b trunk main
Set-Location main
git config user.name "Context Lab"
git config user.email "context-lab@example.invalid"
@('mode=stable','metrics=false') | Set-Content service.conf
Set-Content README.md '# Context Service'
Set-Content .gitignore 'build/'
git add service.conf README.md .gitignore
git commit -m "Create context-switching baseline"
git status --short --branch
git stash list
git worktree list --porcelain
2. Stash one selected path and prove another path remains
Modify both tracked files, then stash only
service.conf:
# Change metrics=false to metrics=true in service.conf.
# Append "draft docs" to README.md.
git status --short
git diff
git stash push -m "service.conf only | metrics experiment" -- service.conf
git status --short
git stash list
git stash show -p stash@{0}
Expected: the service.conf edit is
parked in the stash and restored to HEAD in the current
worktree; the README edit remains in the worktree because it was
outside the pathspec.
git restore -- README.md
git stash apply stash@{0}
git diff -- service.conf
git stash list
git restore -- service.conf
git stash drop stash@{0}
git stash list
apply retained the stash. After proving the saved
change, you restored the disposable working file and explicitly
dropped the entry.
3. Stash staged state without hiding an unrelated unstaged edit
# Change metrics=false to metrics=true in service.conf and stage it.
git add service.conf
# Append "local prose experiment" to README.md but do not stage it.
git status --short
git diff --staged
git diff
git stash push --staged -m "staged metrics change only"
git status --short
git stash show -p stash@{0}
Expected: the staged metrics change moves into the stash, while the unstaged README edit remains visible. This is useful when a staged change belongs to another future task and should not be mixed into the current commit.
git restore -- README.md
git stash pop stash@{0}
git status --short
git diff -- service.conf
git restore -- service.conf
A successful pop removes that stash entry. The restored
metrics edit is intentionally discarded at the end because this is a
disposable demonstration.
4. Decide explicitly whether untracked and ignored files belong in the stash
printf "investigation notes\n" > incident-notes.txt
mkdir -p build
printf "generated cache\n" > build/cache.txt
git status --short --ignored
git stash push -m "tracked only demonstration"
git status --short --ignored
The default stash does not remove the untracked note or ignored build cache. If those files must travel with the temporary context:
git stash drop stash@{0}
git stash push -u -m "include untracked incident notes"
git status --short --ignored
git stash show -u --stat stash@{0}
git stash pop
rm -f incident-notes.txt
rm -rf build
-u includes untracked files but not ignored files.
-a would include ignored content too; use it only after
inspecting exactly what ignored files exist.
5. Engineer a stash-pop conflict and keep the recovery evidence
Create an isolated conflict branch:
git switch -c conflict-demo trunk
printf "mode=feature\n" > conflict.conf
git add conflict.conf
git commit -m "Add conflict baseline"
BASE_CONFLICT=$(git rev-parse HEAD)
printf "mode=stashed\n" > conflict.conf
git stash push -m "conflict demo | stashed value"
STASH_OID=$(git rev-parse stash@{0})
printf "mode=current\n" > conflict.conf
git add conflict.conf
git commit -m "Advance conflict file"
git stash pop stash@{0}
Git should stop with a content conflict. Inspect before repairing:
git status
git diff
git stash list
git rev-parse stash@{0}
Critical observation: because pop failed, the stash entry remains. The failed apply did not erase the only saved copy.
6. Abandon the conflicted application narrowly, then recover with
stash branch
For this one-file disposable conflict, restore the conflicted path
from current HEAD while leaving the stash untouched:
git restore --source=HEAD --staged --worktree -- conflict.conf
git status --short
git stash list
git stash branch recovered-stash stash@{0}
git status --short --branch
cat conflict.conf
git stash list
stash branch creates recovered-stash from
the commit where the stash originally began, applies the saved state
there, and drops the stash entry after successful application. This
avoids forcing old temporary state onto a branch that has since
changed incompatibly.
git add conflict.conf
git commit -m "Preserve recovered stash state"
git switch trunk
7. Create feature, review, and hotfix contexts without switching trunk
From the main worktree:
git worktree add -b feature/metrics ../feature-wt trunk
git worktree add --detach ../review-wt trunk
git worktree add -b hotfix/config ../hotfix-wt trunk
git worktree list
git worktree list --porcelain
git branch -vv
The feature and hotfix directories own named branches. The review worktree uses detached HEAD, which is useful for read-only inspection/testing when you do not want a branch ref to move accidentally.
8. Prove branch checkout exclusivity
git worktree add ../duplicate-feature feature/metrics
The command should refuse because feature/metrics is
already active in ../feature-wt. Inspect
git worktree list --porcelain and use the existing
directory rather than forcing a duplicate checkout.
9. Lock a review worktree, then unlock and move it deliberately
git worktree lock --reason "review snapshot in use" ../review-wt
git worktree list --porcelain
git worktree unlock ../review-wt
git worktree move ../review-wt ../review-wt-renamed
git worktree list --porcelain
Lock protects administrative metadata and also prevents ordinary move/remove operations. Moving with the Git command updates the worktree relationship correctly; do not rename a linked worktree directory in the file manager and assume Git knows the new path.
10. Commit independently in the feature and hotfix worktrees
git -C ../feature-wt config user.name "Feature Worker"
git -C ../feature-wt config user.email "feature@example.invalid"
printf "feature metric work\n" > ../feature-wt/feature.txt
git -C ../feature-wt add feature.txt
git -C ../feature-wt commit -m "Prototype metrics feature"
git -C ../hotfix-wt config user.name "Hotfix Worker"
git -C ../hotfix-wt config user.email "hotfix@example.invalid"
printf "safe=true\n" > ../hotfix-wt/hotfix.conf
git -C ../hotfix-wt add hotfix.conf
git -C ../hotfix-wt commit -m "Prepare configuration hotfix"
git log --graph --decorate --oneline --all --max-count=12
Both commits immediately appear in the common object database and graph, even though their working trees/indexes remain independent.
11. Remove worktrees cleanly and verify branch associations
git worktree remove ../feature-wt
git worktree remove ../hotfix-wt
git worktree remove ../review-wt-renamed
git worktree list --porcelain
git branch -vv
git worktree prune --dry-run
git worktree prune -v
Removing the directories with
git worktree remove cleans their administrative
records. The feature/hotfix branch refs remain unless you delete
them separately. With no stale metadata left, prune should have
nothing to remove.
12. Challenge — choose stash or worktree from the state model
- You have two tracked edits but only one should be parked. Which stash form scopes by path?
- An important staged fix belongs to a different future task while unstaged feature edits should remain visible. Which stash mode targets the index selection?
- A stash conflicts because the branch moved significantly. Which stash command can recreate a branch at the stash's original base?
-
You need a read-only review of
trunkwhile feature work remains untouched. What kind of worktree avoids creating a movable branch? - A linked directory is on removable media that may disappear temporarily. Which worktree command protects its metadata from pruning?
13. Cleanup
Git Bash / Bash / zsh
git stash list
git worktree list
cd ../..
pwd
rm -rf git-context-lab
PowerShell
git stash list
git worktree list
Set-Location ../..
Get-Location
Remove-Item -Recurse -Force git-context-lab
14. Knowledge check
Question 1. Why did stash apply require a later
explicit drop?
Question 2. What happens to a stash entry when
stash pop conflicts?
Question 3. Why did the duplicate feature worktree creation fail?
Question 4. What did git worktree move preserve
that a manual directory rename might not?
Question 5. Does removing a clean worktree delete the branch it had checked out?
15. Summary
You scoped stash entries by path and staged state, inspected and
applied them, handled a failed pop without losing the stash,
recovered via stash branch, created multiple parallel
worktrees, observed branch exclusivity, used lock/move/remove/prune,
and proved that worktrees share commits while keeping checkout state
separate.
Authoritative references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.