Git Worktrees
SkillDev toolsUse when working on multiple branches simultaneously, context switching without stashing, reviewing PRs while developing, testing in isolation, or comparing implementations across branches - provides git worktree commands and workflow patterns for parallel development with multiple working directories.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Git Worktrees skill
What this skill tells your AI
The instructions your AI receives, as published by neolabhq/context-engineering-kit in skills/git-worktrees/SKILL.md and read by ahel’s review.
Overview
Git worktrees enable checking out multiple branches simultaneously in separate directories, all sharing the same repository. Create a worktree instead of stashing changes or cloning separately.
Core principle: One worktree per active branch. Switch contexts by changing directories, not branches.
Core Concepts
| Concept | Description |
|---|---|
| Main worktree | Original working directory from git clone or git init |
| Linked worktree | Additional directories created with git worktree add |
Shared .git | All worktrees share same Git object database (no duplication) |
| Branch lock | Each branch can only be checked out in ONE worktree at a time |
| Worktree metadata | Administrative files in .git/worktrees/ tracking linked worktrees |
Quick Reference
| Task | Command |
|---|---|
| Create worktree (existing branch) | git worktree add <path> <branch> |
| Create worktree (new branch) | git worktree add -b <branch> <path> |
| Create worktree (new branch from ref) | git worktree add -b <branch> <path> <start> |
| Create detached worktree | git worktree add --detach <path> <commit> |
| List all worktrees | git worktree list |
| Remove worktree | git worktree remove <path> |
| Force remove worktree | git worktree remove --force <path> |
| Move worktree | git worktree move <old> <new> |
| Lock worktree | git worktree lock <path> |
| Unlock worktree | git worktree unlock <path> |
| Prune stale worktrees | git worktree prune |
| Repair worktree links | git worktree repair |
| Compare files between worktrees | diff ../worktree-a/file ../worktree-b/file |
| Get one file from another branch | git checkout <branch> -- <path> |
| Get partial file changes | git checkout -p <branch> -- <path> |
| Cherry-pick a commit | git cherry-pick <commit> |
| Cherry-pick without committing | git cherry-pick --no-commit <commit> |
| Merge without auto-commit | git merge --no-commit <branch> |
Essential Commands
Create a Worktree
# Create worktree with existing branch
git worktree add ../feature-x feature-x
# Create worktree with new branch from current HEAD
git worktree add -b new-feature ../new-feature
# Create worktree with new branch from specific commit
git worktree add -b hotfix-123 ../hotfix origin/main
# Create worktree tracking remote branch
git worktree add --track -b feature ../feature origin/feature
# Create worktree with detached HEAD (for experiments)
git worktree add --detach ../experiment HEAD~5
List Worktrees
# Simple list
git worktree list
# Verbose output with additional details
git worktree list -v
# Machine-readable format (for scripting)
git worktree list --porcelain
Example output:
/home/user/project abc1234 [main]
/home/user/project-feature def5678 [feature-x]
/home/user/project-hotfix ghi9012 [hotfix-123]
Remove a Worktree
# Remove worktree (working directory must be clean)
git worktree remove ../feature-x
# Force remove (discards uncommitted changes)
git worktree remove --force ../feature-x
Move a Worktree
# Relocate worktree to new path
git worktree move ../old-path ../new-path
Lock/Unlock Worktrees
# Lock worktree (prevents pruning if on removable storage)
git worktree lock ../feature-x
git worktree lock --reason "On USB drive" ../feature-x
# Unlock worktree
git worktree unlock ../feature-x
Prune Stale Worktrees
# Remove stale worktree metadata (after manual directory deletion)
git worktree prune
# Dry-run to see what would be pruned
git worktree prune --dry-run
# Verbose output
git worktree prune -v
Repair Worktrees
# Repair worktree links after moving directories manually
git worktree repair
# Repair specific worktree
git worktree repair ../feature-x
Workflow Patterns
Pattern 1: Feature + Hotfix in Parallel
To fix a bug while feature work is in progress:
# Create worktree for hotfix from main
git worktree add -b hotfix-456 ../project-hotfix origin/main
# Switch to hotfix directory, fix, commit, push
cd ../project-hotfix
git add . && git commit -m "fix: resolve critical bug #456"
git push origin hotfix-456
# Return to feature work
cd ../project
# Clean up when done
git worktree remove ../project-hotfix
Pattern 2: PR Review While Working
To review a PR without affecting current work:
# Fetch PR branch and create worktree
git fetch origin pull/123/head:pr-123
git worktree add ../project-review pr-123
# Review: run tests, inspect code
cd ../project-review
# Return to work, then clean up
cd ../project
git worktree remove ../project-review
git branch -d pr-123
Pattern 3: Compare Implementations
To compare code across branches side-by-side:
# Create worktrees for different versions
git worktree add ../project-v1 v1.0.0
git worktree add ../project-v2 v2.0.0
# Diff, compare, or run both simultaneously
diff ../project-v1/src/module.js ../project-v2/src/module.js
# Clean up
git worktree remove ../project-v1
git worktree remove ../project-v2
Pattern 4: Long-Running Tasks
To run tests/builds in isolation while continuing development:
# Create worktree for CI-like testing
git worktree add ../project-test main
# Start long-running tests in background
cd ../project-test && npm test &
# Continue development in main worktree
cd ../project
Pattern 5: Stable Reference
To maintain a clean main checkout for reference:
# Create permanent worktree for main branch
git worktree add ../project-main main
# Lock to prevent accidental removal
git worktree lock --reason "Reference checkout" ../project-main
Pattern 6: Selective Merging from Multiple Features
To combine specific changes from multiple feature branches:
# Create worktrees for each feature to review
git worktree add ../project-feature-1 feature-1
git worktree add ../project-feature-2 feature-2
# Review changes in each worktree
diff ../project/src/module.js ../project-feature-1/src/module.js
diff ../project/src/module.js ../project-feature-2/src/module.js
# From main worktree, selectively take changes
cd ../project
git checkout feature-1 -- src/moduleA.js src/utils.js
git checkout feature-2 -- src/moduleB.js
git commit -m "feat: combine selected changes from feature branches"
# Or cherry-pick specific commits
git cherry-pick abc1234 # from feature-1
git cherry-pick def5678 # from feature-2
# Clean up
git worktree remove ../project-feature-1
git worktree remove ../project-feature-2
Comparing and Merging Changes Between Worktrees
Since all worktrees share the same Git repository, you can compare files, cherry-pick commits, and selectively merge changes between them.
Compare and Review File Changes
Since worktrees are just directories, you can compare files directly:
# Compare specific file between worktrees
diff ../project-main/src/app.js ../project-feature/src/app.js
# Use git diff to compare branches (works from any worktree)
git diff main..feature-branch -- src/app.js
# Visual diff with your preferred tool
code --diff ../project-main/src/app.js ../project-feature/src/app.js
# Compare entire directories
diff -r ../project-v1/src ../project-v2/src
Merge Only One File from a Worktree
You can selectively bring a single file from another branch using git checkout:
# In your current branch, get a specific file from another branch
git checkout feature-branch -- path/to/file.js
# Or get it from a specific commit
git checkout abc1234 -- path/to/file.js
# Get multiple specific files
git checkout feature-branch -- src/module.js src/utils.js
For partial file changes (specific hunks/lines only):
# Interactive patch mode - select which changes to take
git checkout -p feature-branch -- path/to/file.js
This prompts you to accept/reject each change hunk individually with options:
y- apply this hunkn- skip this hunks- split into smaller hunkse- manually edit the hunk
Cherry-Pick Commits from Worktrees
Cherry-picking works at the commit level. Since all worktrees share the same repository, you can cherry-pick any commit:
# Find the commit hash (from any worktree or git log)
git log feature-branch --oneline
# Cherry-pick specific commit into your current branch
git cherry-pick abc1234
# Cherry-pick multiple commits
git cherry-pick abc1234 def5678
# Cherry-pick a range of commits
git cherry-pick abc1234^..def5678
# Cherry-pick without committing (stage changes only)
git cherry-pick --no-commit abc1234
Merge Changes from Multiple Worktrees
You can merge or cherry-pick from multiple branches:
# Merge multiple branches sequentially
git merge feature-1
git merge feature-2
# Or use octopus merge for multiple branches at once
git merge feature-1 feature-2 feature-3
# Cherry-pick commits from multiple branches
git cherry-pick abc1234 # from feature-1
git cherry-pick def5678 # from feature-2
Selective Merging - Pick Which Changes to Include
Option 1: Selective File Checkout
# Get specific files from different branches
git checkout feature-1 -- src/moduleA.js
git checkout feature-2 -- src/moduleB.js
git commit -m "Merge selected files from feature branches"
Option 2: Interactive Patch Selection
# Select specific hunks from a file
git checkout -p feature-1 -- src/shared.js
Option 3: Cherry-Pick with Selective Staging
# Apply changes without committing
git cherry-pick --no-commit abc1234
# Unstage what you don't want
git reset HEAD -- unwanted-file.js
git checkout -- unwanted-file.js
# Commit only what you kept
git commit -m "Selected changes from feature-1"
Option 4: Merge with Manual Selection
# Start merge but don't auto-commit
git merge --no-commit feature-1
# Review and modify staged changes
git status
git reset HEAD -- file-to-exclude.js
git checkout -- file-to-exclude.js
# Commit your selection
git commit -m "Merge selected changes from feature-1"
Option 5: Using git restore (Git 2.23+)
# Restore specific file from another branch
git restore --source=feature-branch -- path/to/file.js
# Interactive restore with patch selection
git restore -p --source=feature-branch -- path/to/file.js
Directory Structure Conventions
Organize worktrees predictably:
~/projects/
myproject/ # Main worktree (main/master branch)
myproject-feature-x/ # Feature branch worktree
myproject-hotfix/ # Hotfix worktree
myproject-review/ # Temporary PR review worktree
Naming convention: <project>-<purpose> or <project>-<branch>
Best Practices
| Practice | Rationale |
|---|---|
| Use sibling directories | Keep worktrees at same level as main project for easy navigation |
| Name by purpose | project-review is clearer than project-pr-123 |
| Clean up promptly | Remove worktrees when done to avoid confusion |
| Lock remote worktrees | Prevent pruning if worktree is on network/USB storage |
Use --detach for experiments | Avoid creating throwaway branches |
| Commit before removing | Always commit or stash before git worktree remove |
Common Issues and Solutions
Issue: "Branch is already checked out"
Cause: Attempting to checkout a branch that's active in another worktree.
Solution:
# Find where the branch is checked out
git worktree list
# Either work in that worktree or remove it first
git worktree remove ../other-worktree
Issue: Stale worktree after manual deletion
Cause: Deleted worktree directory without using git worktree remove.
Solution:
# Clean up stale metadata
git worktree prune
Issue: Worktree moved manually
Cause: Moved worktree directory without using git worktree move.
Solution:
# Repair the worktree links
git worktree repair
# Or specify the new path
git worktree repair /new/path/to/worktree
Issue: Worktree on removed drive
Cause: Worktree was on removable storage that's no longer connected.
Solution:
# If temporary, lock it to prevent pruning
git worktree lock ../usb-worktree
# If permanent, prune it
git worktree prune
Common Mistakes
| Mistake | Fix |
|---|---|
Using rm -rf to delete worktree | Always use git worktree remove, then git worktree prune if needed |
| Forgetting branch is locked to worktree | Run git worktree list before checkout errors |
| Not cleaning up temporary worktrees | Remove worktrees immediately after task completion |
| Creating worktrees in nested locations | Use sibling directories (../project-feature) not subdirs |
| Moving worktree directory manually | Use git worktree move or run git worktree repair after |
Agent Workflow Integration
To isolate parallel agent tasks:
# Create worktree for isolated task
git worktree add -b task-123 ../project-task-123
cd ../project-task-123
# Make changes, run tests, return
cd ../project
To experiment safely with detached HEAD:
# Create detached worktree (no branch to clean up)
git worktree add --detach ../project-experiment
cd ../project-experiment
# Experiment, then discard or commit to new branch
git worktree remove --force ../project-experiment
Verification Checklist
Before using worktrees:
- Understand that branches can only be checked out in one worktree
- Know where worktrees will be created (use sibling directories)
- Plan cleanup strategy for temporary worktrees
When creating worktrees:
- Use descriptive directory names
- Verify branch is not already checked out elsewhere
- Consider using
--detachfor experiments
When removing worktrees:
- Commit or stash any uncommitted changes
- Use
git worktree remove, notrm -rf - Run
git worktree pruneif directory was deleted manually
How to Compare Worktrees
Workflow to compare files and directories between git worktrees, helping users understand differences in code across branches or worktrees.
Instructions
CRITICAL: Perform the following steps exactly as described:
-
Current state check: Run
git worktree listto show all existing worktrees and their locations -
Parse user input: Classify each provided argument:
- No arguments: Interactive mode - ask user what to compare
--stat: Show summary statistics of differences (files changed, insertions, deletions)- Worktree path: A path that matches one of the worktree roots from
git worktree list - Branch name: A name that matches a branch in one of the worktrees
- File/directory path: A path within the current worktree to compare
-
Determine comparison targets (worktrees to compare): a. If user provided worktree paths: Use those as comparison targets b. If user specified branch names: Find the worktrees for those branches from
git worktree listc. If only one worktree exists besides current: Use current and that one as comparison targets d. If multiple worktrees exist and none specified: Present list and ask user which to compare e. If no other worktrees exist: Offer to compare with a branch usinggit diff -
Determine what to compare (files/directories within worktrees): a. If user specified file(s) or directory(ies) paths: Compare ALL of them b. If no specific paths given: Ask user:
- "Compare entire worktree?" or
- "Compare specific files/directories? (enter paths)"
-
Execute comparison:
For specific files between worktrees:
diff <worktree1>/<path> <worktree2>/<path> # Or for unified diff format: diff -u <worktree1>/<path> <worktree2>/<path>For directories between worktrees:
diff -r <worktree1>/<directory> <worktree2>/<directory> # Or for summary only: diff -rq <worktree1>/<directory> <worktree2>/<directory>For branch-level comparison (using git diff):
git diff <branch1>..<branch2> -- <path> # Or for stat summary: git diff --stat <branch1>..<branch2>For comparing with current working directory:
diff <current-file> <other-worktree>/<file> -
Format and present results:
- Show clear header indicating what's being compared
- For large diffs, offer to show summary first
- Highlight significant changes (new files, deleted files, renamed files)
- Provide context about the branches each worktree contains
Comparison Modes
| Mode | Description | Command Pattern |
|---|---|---|
| File diff | Compare single file between worktrees | diff -u <wt1>/file <wt2>/file |
| Directory diff | Compare directories recursively | diff -r <wt1>/dir <wt2>/dir |
| Summary only | Show which files differ (no content) | diff -rq <wt1>/ <wt2>/ |
| Git diff | Use git's diff (branch-based) | git diff branch1..branch2 -- path |
| Stat view | Show change statistics | git diff --stat branch1..branch2 |
Worktree Detection
The command finds worktrees using git worktree list:
/home/user/project abc1234 [main]
/home/user/project-feature def5678 [feature-x]
/home/user/project-hotfix ghi9012 [hotfix-123]
From this output, the command extracts:
- Path: The absolute path to the worktree directory
- Branch: The branch name in brackets (used when user specifies branch name)
Examples
Compare specific file between worktrees:
> /worktrees compare src/app.js
# Prompts to select which worktree to compare with
# Shows diff of src/app.js between current and selected worktree
Compare between two specific worktrees:
> /worktrees compare ../project-main ../project-feature src/module.js
# Compares src/module.js between the two specified worktrees
Compare multiple files/directories:
> /worktrees compare src/app.js src/utils/ package.json
# Shows diffs for all three paths between worktrees
Compare entire directories:
> /worktrees compare src/
# Shows all differences in src/ directory between worktrees
Get summary statistics:
> /worktrees compare --stat
# Shows which files differ and line counts
Interactive mode:
> /worktrees compare
# Lists available worktrees
# Asks which to compare
# Asks for specific paths or entire worktree
Compare with branch worktree by branch name:
> /worktrees compare feature-x
# Finds worktree for feature-x branch and compares
Compare specific paths between branch worktrees:
> /worktrees compare main feature-x src/ tests/
# Compares src/ and tests/ directories between main and feature-x worktrees
Output Format
File Comparison Header:
Comparing: src/app.js
From: /home/user/project (main)
To: /home/user/project-feature (feature-x)
---
[diff output]
Summary Output:
Worktree Comparison Summary
===========================
From: /home/user/project (main)
To: /home/user/project-feature (feature-x)
Files only in main:
- src/deprecated.js
Files only in feature-x:
+ src/new-feature.js
+ src/new-feature.test.js
Files that differ:
~ src/app.js
~ src/utils/helpers.js
~ package.json
Statistics:
3 files changed
2 files added
1 file removed
Common Workflows
Review Feature Changes
# See what changed in a feature branch
> /worktrees compare --stat
> /worktrees compare src/components/
Compare Implementations
# Compare how two features implemented similar functionality
> /worktrees compare ../project-feature-1 ../project-feature-2 src/auth/
Quick File Check
# Check if a specific file differs
> /worktrees compare package.json
Pre-Merge Review
# Review all changes before merging (compare src and tests together)
> /worktrees compare --stat
> /worktrees compare src/ tests/
# Both src/ and tests/ directories will be compared
Important Notes
-
Argument detection: The command auto-detects argument types by comparing them against
git worktree listoutput:- Paths matching worktree roots → treated as worktrees to compare
- Names matching branches in worktrees → treated as worktrees to compare
- Other paths → treated as files/directories to compare within worktrees
-
Multiple paths: When multiple file/directory paths are provided, ALL of them are compared between the selected worktrees (not just the first one).
-
Worktree paths: When specifying worktrees, use the full path or relative path from current directory (e.g.,
../project-feature) -
Branch vs Worktree: If you specify a branch name, the command looks for a worktree with that branch checked out. If no worktree exists for that branch, it suggests using
git diffinstead. -
Large diffs: For large directories, the command will offer to show a summary first before displaying full diff output.
-
Binary files: Binary files are detected and reported as "Binary files differ" without showing actual diff.
-
File permissions: The diff will also show changes in file permissions if they differ.
-
No worktrees: If no other worktrees exist, the command will explain how to create one and offer to use
git difffor branch comparison instead.
Integration with Create Worktree
Use /worktrees create first to set up worktrees for comparison:
# Create worktrees for comparison
> /worktrees create feature-x, main
# Created: ../project-feature-x and ../project-main
# Now compare
> /worktrees compare src/
Troubleshooting
"No other worktrees found"
- Create a worktree first with
/worktrees create <branch> - Or use
git difffor branch-only comparison without worktrees
"Worktree for branch not found"
- The branch may not have a worktree created
- Run
git worktree listto see available worktrees - Create the worktree with
/worktrees create <branch>
"Path does not exist in worktree"
- The specified file/directory may not exist in one of the worktrees
- This could indicate the file was added/deleted in one branch
- The command will report this in the comparison output
How to Create Worktree
Workflow to create and setup git worktrees for parallel development, with automatic detection and installation of project dependencies.
Instructions
CRITICAL: Perform the following steps exactly as described:
-
Current state check: Run
git worktree listto show existing worktrees andgit statusto verify the repository state is clean (no uncommitted changes that might cause issues) -
Fetch latest remote branches: Run
git fetch --allto ensure local has knowledge of all remote branches -
Parse user input: Determine what the user wants to create:
<name>: Create worktree with auto-detected type prefix--list: Just show existing worktrees and exit- No input: Ask user interactively for the name
-
Auto-detect branch type from name: Check if the first word is a known branch type. If yes, use it as the prefix and the rest as the name. If no, default to
feature/.Known types:
feature,feat,fix,bug,bugfix,hotfix,release,docs,test,refactor,chore,spike,experiment,reviewExamples:
refactor auth system→refactor/auth-systemfix login bug→fix/login-bugauth system→feature/auth-system(default)hotfix critical error→hotfix/critical-error
Name normalization: Convert spaces to dashes, lowercase, remove special characters except dashes/underscores
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 2k
- Forks
- 157
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
git-worktrees-neolabhq- Source
- github.com/neolabhq/context-engineering-kit