skills/git-worktree/SKILL.md
Manage multiple working directories with git worktree for parallel development
npx skillsauth add jcsaaddupuy/badrobots git-worktreeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Git worktree allows you to maintain multiple working directories from a single repository. Each worktree can check out a different branch simultaneously, enabling parallel development without the need for stashing, switching branches, or cloning the repository multiple times.
Key Benefits:
.git directory (saves disk space)my-project/ # Main worktree (original clone)
├── .git/ # Shared Git database
│ └── worktrees/ # Worktree metadata
│ ├── feature-login/
│ └── hotfix-bug/
└── src/
my-project-feature-login/ # Linked worktree
└── src/ # Same repo, different branch
my-project-hotfix/ # Another linked worktree
└── src/ # Same repo, yet another branch
All worktrees share the same .git directory but have independent:
Basic Usage:
# Create new worktree with existing branch
git worktree add <path> <branch>
# Create new worktree with new branch
git worktree add -b <new-branch> <path> <start-point>
Examples:
# Checkout existing branch in new worktree
git worktree add ../my-project-feature feature/login
# Create new branch from main and check it out
git worktree add -b feature/new-ui ../my-project-ui main
# Create worktree for hotfix from current branch
git worktree add ../hotfix-123 -b hotfix/fix-crash
# Detached HEAD worktree (for testing specific commit)
git worktree add --detach ../test-commit abc1234
# Force add even if branch is already checked out elsewhere
git worktree add -f ../duplicate-work feature/login
Options:
-b <branch> - Create new branch-B <branch> - Create/reset branch (overwrites if exists)-f, --force - Allow checking out branch already used by another worktree--detach - Create detached HEAD worktree--lock - Lock the worktree immediately after creation--orphan - Create new orphan branch (no history)--checkout / --no-checkout - Control whether to checkout filesBasic Usage:
git worktree list
Examples:
# Default format (human-readable)
git worktree list
# Verbose output (includes branch, commit, lock status)
git worktree list -v
# Machine-parseable format
git worktree list --porcelain
# For scripting with null-terminated output
git worktree list --porcelain -z
Sample Output:
$ git worktree list
/Users/me/project abc123 [main]
/Users/me/project-feature def456 [feature/login]
/Users/me/project-hotfix 789ghi (detached HEAD)
$ git worktree list -v
/Users/me/project abc123 [main]
/Users/me/project-feature def456 [feature/login]
/Users/me/project-hotfix 789ghi (detached HEAD) locked
Basic Usage:
git worktree remove <path>
Examples:
# Remove clean worktree
git worktree remove ../my-project-feature
# Force remove worktree with uncommitted changes
git worktree remove -f ../my-project-feature
# Force remove locked worktree (use -f twice)
git worktree remove -f -f ../locked-worktree
Options:
-f, --force - Remove even with uncommitted changes-f -f (twice) to remove locked worktreesManual Removal: If you delete a worktree directory manually:
# Clean up stale worktree references
git worktree prune
Basic Usage:
git worktree move <old-path> <new-path>
Examples:
# Move worktree to new location
git worktree move ../project-feature ../renamed-feature
# Move to different parent directory
git worktree move ../hotfix ~/workspace/hotfix
Limitations:
Purpose: Prevent accidental removal or administrative pruning
Lock:
# Lock with reason
git worktree lock --reason "CI/CD in progress" ../ci-worktree
# Lock without reason
git worktree lock ../important-worktree
Unlock:
git worktree unlock ../ci-worktree
Use Cases:
Purpose: Clean up metadata for manually deleted worktrees
Basic Usage:
git worktree prune
Examples:
# Dry-run (show what would be removed)
git worktree prune -n
# Verbose output
git worktree prune -v
# Prune worktrees unused for 30 days
git worktree prune --expire 30.days.ago
# Prune everything immediately
git worktree prune --expire now
When to Use:
Purpose: Fix broken connections after moving repositories or worktrees manually
Basic Usage:
# Repair all worktrees
git worktree repair
# Repair specific worktree
git worktree repair ../broken-worktree
# Repair from within a worktree
cd ../broken-worktree
git worktree repair
When to Use:
.git directoryScenario: Working on feature, urgent hotfix needed
# Currently working on feature in main worktree
cd ~/project
git checkout -b feature/new-ui
# Urgent bug reported! Create hotfix worktree
git worktree add -b hotfix/critical-bug ../project-hotfix main
# Work on hotfix in separate directory
cd ../project-hotfix
# ... fix bug ...
git commit -am "Fix critical bug"
git push origin hotfix/critical-bug
# Return to feature work (no branch switching!)
cd ~/project
# Continue working on feature...
# Clean up hotfix worktree after merge
git worktree remove ../project-hotfix
Scenario: Review PR without interrupting current work
# Working on feature
cd ~/project
git checkout feature/payment
# Need to review teammate's PR
git worktree add ../project-review feature/teammate-work
# Review in separate window/IDE
cd ../project-review
# ... review code, test, comment ...
# Back to your work immediately
cd ~/project
# No stashing or branch switching needed!
# Clean up review worktree
git worktree remove ../project-review
Scenario: Working on multiple features simultaneously
cd ~/project
# Create worktrees for different features
git worktree add -b feature/auth ../project-auth main
git worktree add -b feature/payments ../project-payments main
git worktree add -b feature/analytics ../project-analytics main
# Work on each in separate terminal/IDE instance
# Each has its own uncommitted changes, no conflicts!
# List all active worktrees
git worktree list
# Clean up completed features
git worktree remove ../project-auth
Scenario: Test multiple branches before release
# Create worktrees for release candidates
git worktree add ../test-v1 release/v1.0
git worktree add ../test-v2 release/v2.0
git worktree add ../test-main main
# Run tests in each
cd ../test-v1 && make test
cd ../test-v2 && make test
cd ../test-main && make test
# Compare results without branch switching
Scenario: Dedicated worktree for automated builds
# Create locked worktree for CI
git worktree add --lock --reason "Jenkins build agent" ../ci-build main
# CI system uses this directory
# Lock prevents accidental removal
# When no longer needed
git worktree unlock ../ci-build
git worktree remove ../ci-build
Use descriptive paths:
# ✅ Good - clear purpose
git worktree add ../project-feature-login feature/login
git worktree add ../project-hotfix-123 hotfix/issue-123
git worktree add ../project-review-pr456 feature/teammate-work
# ❌ Avoid - unclear names
git worktree add ../temp feature/login
git worktree add ../test hotfix/issue-123
Consistent structure:
# Pattern: <project>-<purpose>-<identifier>
~/workspace/
├── myapp/ # Main worktree
├── myapp-feature-auth/ # Feature development
├── myapp-hotfix-crash/ # Hotfix
└── myapp-review-pr123/ # Code review
Keep worktrees close to main:
# ✅ Good - easy to find and manage
~/project/
~/project-feature-login/
~/project-hotfix/
# ❌ Avoid - scattered across filesystem
~/project/
~/Documents/temp-feature/
/tmp/hotfix/
Alternative: Parent directory approach:
~/workspace/myapp/
├── main/ # Main worktree (renamed)
├── feature-login/ # Worktrees at same level
├── hotfix-123/
└── review-pr456/
# Weekly cleanup routine
git worktree list
git worktree remove <completed-worktrees>
git worktree prune --dry-run
git worktree prune
Automate cleanup:
#!/bin/bash
# cleanup-worktrees.sh
echo "Current worktrees:"
git worktree list
echo -e "\nStale worktrees to prune:"
git worktree prune -v --dry-run
read -p "Proceed with pruning? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
git worktree prune -v
fi
One branch per worktree (mostly):
# ✅ Good - each worktree has unique branch
git worktree add -b feature/login ../project-login
git worktree add -b feature/payments ../project-payments
# ⚠️ Use force sparingly - can cause confusion
git worktree add -f ../duplicate main # Both have main checked out
Create branches explicitly:
# ✅ Good - clear intent
git worktree add -b feature/new-api ../api-work main
# ❌ Avoid - auto-generated branch name
git worktree add ../api-work
# Creates branch like "api-work" automatically
# Lock worktrees that shouldn't be deleted
git worktree lock --reason "Production deployment staging" ../deploy
# Lock CI/CD worktrees
git worktree lock --reason "Jenkins workspace" ../jenkins-build
# Always unlock when done
git worktree unlock ../deploy
Worktrees with submodules have limitations:
# Cannot move worktrees containing submodules
# Must remove and recreate instead
# If you need to work with submodules
cd worktree-with-submodules
git submodule update --init --recursive
Cause: Branch is checked out in another worktree
Solutions:
# Option 1: Remove the other worktree first
git worktree remove <other-path>
# Option 2: Use --force (be careful!)
git worktree add -f ../duplicate-work feature/branch
# Option 3: Create new branch instead
git worktree add -b feature/branch-v2 ../new-work feature/branch
Solution:
# Git still tracks it - clean up metadata
git worktree prune -v
# Verify it's gone
git worktree list
Solution:
# Repair all connections
git worktree repair
# Or repair from within broken worktree
cd broken-worktree
git worktree repair
# Check status
git worktree list
Solution:
# Option 1: Commit or stash changes first
cd worktree
git stash
git worktree remove .
# Option 2: Force remove (loses changes!)
git worktree remove -f ../worktree
Solution:
# Option 1: Unlock first
git worktree unlock ../worktree
git worktree remove ../worktree
# Option 2: Force remove (use -f twice)
git worktree remove -f -f ../locked-worktree
Solution:
# This shouldn't happen normally
# If it does, worktree might be corrupted
# Check actual state
cd worktree
git status
git branch
# If broken, remove and recreate
cd ..
git worktree remove worktree
git worktree add worktree branch-name
# Add to ~/.bashrc or ~/.zshrc
wtadd() {
local branch="$1"
local path="$2"
if [ -z "$branch" ]; then
echo "Usage: wtadd <branch> [path]"
return 1
fi
# Default path if not provided
if [ -z "$path" ]; then
# Extract repo name from current directory
local repo=$(basename $(git rev-parse --show-toplevel))
path="../${repo}-${branch//\//-}"
fi
git worktree add "$path" "$branch"
}
# Usage
wtadd feature/login # Auto path
wtadd hotfix/bug-123 ../fix # Custom path
wtlist() {
echo "Active Worktrees:"
echo "================="
git worktree list | while read -r line; do
local path=$(echo "$line" | awk '{print $1}')
local branch=$(echo "$line" | grep -o '\[.*\]' | tr -d '[]')
if [ -n "$branch" ]; then
echo "📁 $path"
echo " Branch: $branch"
# Show if there are uncommitted changes
if [ -d "$path" ]; then
cd "$path" &>/dev/null
if ! git diff-index --quiet HEAD 2>/dev/null; then
echo " ⚠️ Uncommitted changes"
fi
cd - &>/dev/null
fi
fi
done
}
wtclean() {
local main_branch="${1:-main}"
echo "Finding merged branches..."
git worktree list --porcelain | grep -A 3 "^worktree" | while read -r line; do
if [[ $line =~ ^worktree ]]; then
local wt_path=$(echo "$line" | awk '{print $2}')
elif [[ $line =~ ^branch ]]; then
local branch=$(echo "$line" | sed 's/^branch refs\/heads\///')
# Check if branch is merged
if git branch --merged "$main_branch" | grep -q "^[* ] $branch$"; then
echo "✓ $branch is merged - removing worktree at $wt_path"
git worktree remove "$wt_path"
fi
fi
done
# Cleanup stale metadata
git worktree prune -v
}
#!/bin/bash
# parallel-tests.sh - Test multiple branches in parallel
branches=("main" "develop" "feature/new-api")
for branch in "${branches[@]}"; do
worktree="../test-${branch//\//-}"
# Create worktree
git worktree add "$worktree" "$branch" || continue
# Run tests in background
(
cd "$worktree"
echo "Testing $branch..."
make test > "../test-${branch//\//-}.log" 2>&1
echo "✓ $branch tests complete"
) &
done
# Wait for all background jobs
wait
# Show results
for branch in "${branches[@]}"; do
echo "Results for $branch:"
cat "../test-${branch//\//-}.log"
done
# Cleanup
for branch in "${branches[@]}"; do
git worktree remove "../test-${branch//\//-}"
done
#!/bin/bash
# create-review-worktrees.sh
# Get open PRs (using GitHub CLI)
gh pr list --json number,headRefName | jq -r '.[] | "\(.number) \(.headRefName)"' | \
while read -r number branch; do
worktree="../review-pr-$number"
if [ ! -d "$worktree" ]; then
echo "Creating worktree for PR #$number ($branch)"
git worktree add "$worktree" "$branch"
fi
done
# Create temporary worktree for quick test
test-commit() {
local commit="${1:-HEAD}"
local temp_dir=$(mktemp -d)
echo "Creating test worktree at $temp_dir"
git worktree add --detach "$temp_dir" "$commit"
# Open in new terminal or editor
cd "$temp_dir"
# Cleanup on exit
trap "git worktree remove -f '$temp_dir'" EXIT
}
# Create worktree with specific config
git worktree add ../work-email feature/work
cd ../work-email
git config user.email "[email protected]"
git config user.name "Work Name"
# Main worktree keeps personal config
cd -
git config user.email "[email protected]"
Advantages:
cd)Limitations:
--force)node_modules, venv, etc. not sharedDisk Space Example:
# Full clone approach
repo1/ 1.2 GB
repo2/ 1.2 GB
repo3/ 1.2 GB
Total: 3.6 GB
# Worktree approach
main/ 1.2 GB (.git shared)
worktree1/ 0.2 GB (working files only)
worktree2/ 0.2 GB (working files only)
Total: 1.6 GB
Use worktrees when:
Don't use worktrees when:
git checkout)Related skills:
# CREATE
git worktree add <path> <branch> # Existing branch
git worktree add -b <new> <path> <base> # New branch
git worktree add --detach <path> <commit> # Detached HEAD
# MANAGE
git worktree list # Show all
git worktree list --porcelain # Script-friendly
git worktree move <old> <new> # Move
git worktree remove <path> # Remove
git worktree remove -f <path> # Force remove
# LOCK/UNLOCK
git worktree lock --reason <msg> <path> # Lock
git worktree unlock <path> # Unlock
# MAINTENANCE
git worktree prune # Clean stale
git worktree prune -n # Dry-run
git worktree repair # Fix broken
# COMMON PATTERNS
git worktree add ../proj-hotfix -b hotfix/123 main
git worktree add ../proj-review feature/pr-456
git worktree remove ../proj-feature
git worktree list -v | grep locked
development
DuckDB patterns for JSON/JSONL analysis, array unnesting, and common gotchas. Use when querying JSON files, nested data, or encountering "UNNEST not supported here" errors.
development
Mealie recipe manager API: recipes, shopping lists, meal plans. Requires MEALIE_BASE_URL and MEALIE_API_KEY.
business
TimeWarrior time tracking: start/stop intervals, query durations by tag or issue, compute totals for issue tracker time reporting
development
Bookmark manager for saving, searching, and annotating web content. Use when: (1) saving a webpage for later reference, (2) searching previously saved bookmarks, (3) adding highlights/annotations to saved content, (4) user asks to 'bookmark this' or 'save this article'. Requires READECK_BASE_URL and READECK_API_KEY environment variables.