previewing-changes-in-worktrees
Drafts a change in a sparse git worktree, shows it side by side in nvim/tmux, then merges it in. Use to show or preview a diff.
SKILL.mdclaude-skills/previewing-changes-in-worktrees/SKILL.md
GitHubPreviewing changes in worktrees
Use when the user wants to see a proposed change as a real diff before it lands, e.g. during
plan review ("show me the diff", "open it side by side"). The draft lives in a throwaway worktree
outside the checkout; the user's files, index, stash and config stay untouched until
worktree_apply.
The functions are plain bash in scripts/sparse_worktree.sh; read its header for what each
does. The Bash tool starts a fresh shell per call, so source it in every call:
source ~/.claude/skills/previewing-changes-in-worktrees/scripts/sparse_worktree.sh && <function> ...
Steps
- From inside the source checkout, create the worktree with every file the change touches,
including files it will create. It snapshots the working tree, uncommitted edits included
(~3 s on the monorepo):
It prints the worktree path,... && sparse_worktree excess_speed learning/x/a.py learning/x/BUILD learning/x/new.yaml$SPARSE_WORKTREE_ROOT/<name>(default/tmp/sparse_worktrees). - Edit the copies under that path with Read/Edit/Write, never the checkout. Batch independent
edits in one message. More files later:
sparse_worktree_add <name> <files...>. To delete a file:git -C <worktree> rm <file>. - Show it:
worktree_diff <name>opens a tmux split runninggit difftool -t nvimdiff, one file at a time, base on the left; it prints the pane id. The pane closes after the last file. After further edits, rerun withworktree_diff <name> <pane id>: it reuses the pane if it is still open, else splits anew. Tell the user:]c/[cjump between changes,:qamoves to the next file,:cqstops.worktree_patch <name>writes<root>/<name>.patchif they want the file. - Once approved,
worktree_apply <name>merges each changed file into the checkout withgit merge-file. It never stages anything. If a file changed in the checkout since the snapshot, both changes are kept; overlapping ones get conflict markers, aconflict: <file>line, and a non-zero exit. Resolve those before going on. worktree_remove <name>. Build, lint and test in the checkout, not the worktree: it holds only the listed files.
Gotchas
- Paths are repo-relative, and
sparse_worktreemust run inside the checkout it snapshots. - Never type into the user's shell with
tmux send-keys;worktree_diffspawns or respawns its own pane.