Git: Stashing and Worktrees
Sometimes you're in the middle of work and need to switch contexts — a colleague needs a quick review, there's an urgent bug, or you just need a clean state temporarily. git stash sets your work aside without committing. git worktree goes further: it lets you check out multiple branches simultaneously in separate directories. git sparse-checkout lets you work with only a subset of a large repository.
Commands Covered
git stash · git worktree · git sparse-checkout
git stash
Saves dirty working tree state (staged and unstaged changes) onto a stack, then reverts to a clean HEAD. You can pop the stash later to restore your work.
# Stash current changes (tracked files only)
$ git stash
$ git stash push
# Stash with a descriptive message
$ git stash push -m "WIP: half-finished auth refactor"
# Include untracked files in the stash
$ git stash push -u
$ git stash push --include-untracked
# Include ignored files too
$ git stash push -a
$ git stash push --all
# Stash only specific files
$ git stash push -- src/auth.c src/session.c
# List all stashes
$ git stash list
# stash@{0}: WIP on main: abc1234 Fix login bug
# stash@{1}: WIP: half-finished auth refactor
# stash@{2}: WIP on feature: def5678 Add search
# Apply the most recent stash (keeps it in the stash list)
$ git stash apply
# Apply a specific stash
$ git stash apply stash@{2}
# Pop the most recent stash (apply and remove from list)
$ git stash pop
# Pop a specific stash
$ git stash pop stash@{1}
# Show what's in a stash (diff)
$ git stash show -p
$ git stash show -p stash@{1}
# Show stash as a list of files
$ git stash show --stat
# Drop (delete) a stash without applying
$ git stash drop stash@{1}
# Clear all stashes
$ git stash clear
Creating a Branch from a Stash
# If applying a stash causes conflicts (context changed since you stashed):
$ git stash branch new-branch-name stash@{0}
# Creates a new branch from the commit the stash was based on,
# applies the stash to it, and drops the stash if successful.
Stash Partial Changes
# Stash interactively — choose which hunks to stash $ git stash push -p # Same y/n/s prompts as git add -p
git worktree
Allows you to check out multiple branches simultaneously, each in its own directory. All worktrees share the same .git directory. Useful when you need to compare branches side-by-side, work on a hotfix without stashing, or run tests on multiple branches simultaneously.
# Add a new worktree for a branch $ git worktree add ../hotfix-dir hotfix-branch # Creates a new directory ../hotfix-dir checked out to hotfix-branch # Add a worktree and create a new branch at the same time $ git worktree add -b emergency-fix ../emergency ../main # List all worktrees $ git worktree list # /home/user/my-repo abc1234 [main] # /home/user/hotfix-dir def5678 [hotfix-branch] # /home/user/emergency ghi9012 [emergency-fix] # Remove a worktree (must be done from the main worktree) $ git worktree remove ../hotfix-dir # Or manually delete the directory, then: $ git worktree prune # Lock a worktree (prevent accidental removal) $ git worktree lock ../hotfix-dir --reason "In active use by CI" $ git worktree unlock ../hotfix-dir
Worktree Rules
# Each branch can only be checked out in one worktree at a time. # Trying to check out an active branch in a second worktree fails: $ git worktree add ../copy main # fatal: 'main' is already checked out at '/home/user/my-repo' # You CAN check out different branches simultaneously: # Main worktree: main # Extra worktree: feature-login # Extra worktree: hotfix-v2 # Detached HEAD works in worktrees: $ git worktree add --detach ../review abc1234
git sparse-checkout
Lets you check out only a subset of files from a large repository. Useful when a monorepo is too large to fully check out, or when you only need part of a repo.
# Enable sparse-checkout (cone mode — the simpler, faster mode) $ git sparse-checkout init --cone # Set which directories to check out $ git sparse-checkout set src/api src/web # Now only src/api/ and src/web/ are checked out; other dirs are absent # Add more directories $ git sparse-checkout add src/shared # List current sparse-checkout patterns $ git sparse-checkout list # Disable sparse-checkout (restore full checkout) $ git sparse-checkout disable # Non-cone mode (pattern-based, more flexible but slower) $ git sparse-checkout init $ git sparse-checkout set '/*' '!/docs/' # everything except docs/ # Combined with --depth for minimal clone of a large repo: $ git clone --depth 1 --filter=blob:none --sparse https://github.com/large/repo.git $ cd repo $ git sparse-checkout init --cone $ git sparse-checkout set src/module-i-need
dispelled