use-git-worktree · git:20260912.480a145 · 2026-09-12 · sha256 40344f95c03bafdb
use-git-worktree git:20260912.480a145A
Immutable. This exact content is served forever at /api/v1/blob/40344f95c03bafdb.
---
name: use-git-worktree
description: This skill should be used when starting feature work that needs isolation from current workspace - creates isolated git worktrees with smart directory selection and safety verification
user-invocable: false
---
# Git Worktree Management
Create and manage isolated git worktrees for task execution with automatic project setup and merge handling.
## Overview
Git worktrees provide complete isolation for task work:
- Changes don't affect main workspace until merge
- Can switch between tasks without stashing
- Clean baseline for each task
- Safe to experiment
## Workflow
### Step 1: Determine Worktree Directory
Find or create the worktree directory using this priority order:
1. **Check for existing directory:**
```bash
# Preferred (hidden, less clutter)
ls -d .worktrees 2>/dev/null
# Alternative
ls -d worktrees 2>/dev/null
```
2. **Check CLAUDE.md for directive:**
```markdown
worktree-dir: path/to/worktrees
```
3. **Check README.md for configuration:**
Look for worktree or development setup instructions.
4. **Ask user if not found:**
> "Where should I create worktrees for isolated task work?
> 1. `.worktrees/` (Recommended - hidden, less clutter)
> 2. `worktrees/`
> 3. Custom location"
### Step 2: Verify Directory is Gitignored
**Critical:** Ensure the worktree directory won't be committed.
```bash
git check-ignore -q <worktree-dir>
```
**If not ignored:**
- Add to `.gitignore` with user confirmation
- Report the change
```bash
echo "<worktree-dir>/" >> .gitignore
```
### Step 3: Create Branch and Worktree
**Resolve the workspace identity with the shared helper — never derive it by hand.**
Task IDs are only unique per project (each project numbers its own `specs/tasks.md`), so the branch and worktree path must be project-qualified in monorepos. The helper applies the same convention the terminal runner uses, so interactive sessions and runner runs share one identity space and can never silently collide:
```bash
node ${CLAUDE_PLUGIN_ROOT}/lib/worktree-identity.js TASK-004
```
Output (single JSON line):
```json
{"task_id":"TASK-004","repo_root":"…","project_root":"…","project_name":"web",
"scope":"project","path":"<repo>/.worktrees/web-TASK-004","branch":"task/web/TASK-004",
"legacy":{"path":"<repo>/.worktrees/TASK-004","branch":"task/TASK-004","exists":false,"runner_owner":null}}
```
Rules:
- Use the returned `path` and `branch` **verbatim** — including in merges, cleanup, and reports. Single-project repos get the short form (`task/TASK-004`, `<dir>/TASK-004`); monorepos get the project-qualified form.
- If `legacy.exists` is true, a pre-scoping unqualified worktree exists at the repository root: surface it to the user ("if it belongs to another project, remove it; if it's yours, continue working in it") instead of silently adopting or ignoring it.
- If `legacy.runner_owner` names a project, that legacy worktree is owned by a runner run's checkpoint — do not reuse it without the user's explicit confirmation.
**Create from current HEAD:**
```bash
# Get current branch as base
BASE_BRANCH=$(git branch --show-current)
# Create branch and worktree in one command, using the helper's values
git worktree add -b <branch> <worktree-path>
```
**Record context (used by every later merge/cleanup step):**
- Base branch (for later merge)
- Worktree path (`<worktree-path>`)
- Branch (`<branch>`)
- Task ID
### Step 4: Auto-Detect and Run Project Setup
Change to worktree directory and detect project type:
| File Present | Setup Command |
|--------------|---------------|
| `package.json` | `npm install` or `yarn install` |
| `Cargo.toml` | `cargo build` |
| `requirements.txt` | `pip install -r requirements.txt` |
| `Pipfile` | `pipenv install` |
| `pyproject.toml` | `pip install -e .` or `poetry install` |
| `go.mod` | `go mod download` |
| `Gemfile` | `bundle install` |
| `pom.xml` | `mvn install` |
| `build.gradle` | `./gradlew build` |
**Check for custom setup:**
1. Read CLAUDE.md for setup instructions
2. Read README.md for development setup section
3. Execute any documented setup steps
### Step 5: Verify Baseline Tests Pass
Run the project's test suite to ensure a clean starting point:
```bash
# Detect test command from package.json, Makefile, etc.
npm test # Node.js
cargo test # Rust
pytest # Python
go test ./... # Go
bundle exec rspec # Ruby
```
**If tests fail:**
> "Baseline tests are failing in the worktree. This may indicate:
> 1. Setup incomplete - check dependencies
> 2. Tests require specific environment
> 3. Base branch has failing tests
>
> Would you like to:
> 1. Continue anyway (tests may already be failing)
> 2. Abort and investigate"
### Step 6: Return Worktree Context
Provide context for the calling skill:
```markdown
## Worktree Created
**Task:** TASK-NNN
**Branch:** <branch from the helper>
**Base Branch:** main
**Working Directory:** <worktree-path from the helper>
**Merge Mode:** [auto-merge|manual]
Project setup complete. Baseline tests passing.
Ready to begin work.
```
## Merge Operations
### Auto-Merge Flow
When task completes with auto-merge enabled:
```bash
# Ensure all changes committed in worktree
cd <worktree-path>
git status --porcelain # Should be empty
# Return to main repo and merge (branch/worktree-path as recorded in Step 3)
cd <original-repo>
git checkout <base-branch>
git merge --no-ff <task-branch> -m "Merge <task-branch>: [Task Title]"
# Cleanup
git worktree remove <worktree-path>
git branch -d <task-branch>
```
### Manual Verification Flow
When user wants to review before merge:
```markdown
## Task Complete in Worktree
**Location:** <worktree-path>
**Branch:** <task-branch>
All changes committed. To merge manually:
```bash
git checkout <base-branch>
git merge --no-ff <task-branch>
git worktree remove <worktree-path>
git branch -d <task-branch>
```
Or to continue working:
```bash
cd <worktree-path>
```
```
### Merge Conflict Handling
If merge conflicts occur:
```markdown
## Merge Conflict
The merge of <task-branch> into <base-branch> has conflicts.
**Conflicting files:**
- path/to/file1.ts
- path/to/file2.ts
**Options:**
1. Resolve conflicts manually in the main repo
2. Abort merge and keep worktree for investigation
**To resolve:**
```bash
# In main repo after failed merge
git status # See conflicting files
# Edit files to resolve conflicts
git add <resolved-files>
git commit # Complete merge
# Then cleanup
git worktree remove <worktree-path>
git branch -d <task-branch>
```
**To abort:**
```bash
git merge --abort
# Worktree preserved at <worktree-path>
```
```
## Error Handling
| Error | Recovery |
|-------|----------|
| Branch already exists | Another session (or a runner run) may hold this task — run `git worktree list`, offer to reuse the existing worktree, wait, or clean it up |
| Worktree path exists | Check if it's valid, offer cleanup or different path |
| Not a git repository | Cannot use worktrees, fall back to current directory |
| Uncommitted changes | Prompt to commit or stash before creating worktree |
| Setup command fails | Report error, offer to continue or abort |
## Cleanup Commands
**Remove a worktree:**
```bash
git worktree remove <path>
git branch -d <branch> # Safe delete (checks merge status)
git branch -D <branch> # Force delete
```
**List all worktrees:**
```bash
git worktree list
```
**Prune stale worktrees:**
```bash
git worktree prune
```