mirror of
https://github.com/obra/superpowers.git
synced 2026-04-20 16:39:04 +08:00
feat: rewrite using-git-worktrees with detect-and-defer (PRI-974)
Step 0: GIT_DIR != GIT_COMMON detection (skip if already isolated) Step 0 consent: opt-in prompt before creating worktree (#991) Step 1a: native tool preference (short, first, declarative) Step 1b: git worktree fallback with hooks symlink and legacy path compat Submodule guard prevents false detection Platform-neutral instruction file references (#1049) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,104 +1,126 @@
|
||||
---
|
||||
name: using-git-worktrees
|
||||
description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
|
||||
description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - ensures an isolated workspace exists via native tools or git worktree fallback
|
||||
---
|
||||
|
||||
# Using Git Worktrees
|
||||
|
||||
## Overview
|
||||
|
||||
Git worktrees create isolated workspaces sharing the same repository, allowing work on multiple branches simultaneously without switching.
|
||||
Ensure work happens in an isolated workspace. Prefer your platform's native worktree tools. Fall back to manual git worktrees only when no native tool is available.
|
||||
|
||||
**Core principle:** Systematic directory selection + safety verification = reliable isolation.
|
||||
**Core principle:** Detect existing isolation first. Then use native tools. Then fall back to git. Never fight the harness.
|
||||
|
||||
**Announce at start:** "I'm using the using-git-worktrees skill to set up an isolated workspace."
|
||||
|
||||
## Directory Selection Process
|
||||
## Step 0: Detect Existing Isolation
|
||||
|
||||
**Before creating anything, check if you are already in an isolated workspace.**
|
||||
|
||||
```bash
|
||||
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
||||
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
||||
BRANCH=$(git branch --show-current)
|
||||
```
|
||||
|
||||
**Submodule guard:** `GIT_DIR != GIT_COMMON` is also true inside git submodules. Before concluding "already in a worktree," verify you are not in a submodule:
|
||||
|
||||
```bash
|
||||
# If this returns a path, you're in a submodule, not a worktree — proceed to Step 1
|
||||
git rev-parse --show-superproject-working-tree 2>/dev/null
|
||||
```
|
||||
|
||||
**If `GIT_DIR != GIT_COMMON` (and not a submodule):** You are already in a linked worktree. Skip to Step 3 (Project Setup). Do NOT create another worktree.
|
||||
|
||||
Report with branch state:
|
||||
- On a branch: "Already in isolated workspace at `<path>` on branch `<name>`."
|
||||
- Detached HEAD: "Already in isolated workspace at `<path>` (detached HEAD, externally managed). Branch creation needed at finish time."
|
||||
|
||||
**If `GIT_DIR == GIT_COMMON` (or in a submodule):** You are in a normal repo checkout. Ask for consent before creating a workspace:
|
||||
|
||||
> "Would you like me to set up an isolated worktree? This protects your current branch from changes. (y/n)"
|
||||
|
||||
If yes, proceed to Step 1. If no, work in place — skip to Step 3 with no worktree.
|
||||
|
||||
## Step 1: Create Isolated Workspace
|
||||
|
||||
**You have two mechanisms. Try them in this order.**
|
||||
|
||||
### 1a. Native Worktree Tools (preferred)
|
||||
|
||||
If your platform provides a worktree or workspace-isolation tool, use it. You know your own toolkit — the skill does not need to name specific tools. Native tools handle directory placement, branch creation, and cleanup automatically.
|
||||
|
||||
After using a native tool, skip to Step 3 (Project Setup).
|
||||
|
||||
### 1b. Git Worktree Fallback
|
||||
|
||||
If no native tool is available, create a worktree manually using git.
|
||||
|
||||
#### Directory Selection
|
||||
|
||||
Follow this priority order:
|
||||
|
||||
### 1. Check Existing Directories
|
||||
1. **Check existing directories:**
|
||||
```bash
|
||||
ls -d .worktrees 2>/dev/null # Preferred (hidden)
|
||||
ls -d worktrees 2>/dev/null # Alternative
|
||||
```
|
||||
If found, use that directory. If both exist, `.worktrees` wins.
|
||||
|
||||
```bash
|
||||
# Check in priority order
|
||||
ls -d .worktrees 2>/dev/null # Preferred (hidden)
|
||||
ls -d worktrees 2>/dev/null # Alternative
|
||||
```
|
||||
2. **Check for existing global directory:**
|
||||
```bash
|
||||
project=$(basename "$(git rev-parse --show-toplevel)")
|
||||
ls -d ~/.config/superpowers/worktrees/$project 2>/dev/null
|
||||
```
|
||||
If found, use it (backward compatibility with legacy global path).
|
||||
|
||||
**If found:** Use that directory. If both exist, `.worktrees` wins.
|
||||
3. **Check your project's agent instruction file** (CLAUDE.md, GEMINI.md, AGENTS.md, .cursorrules, or equivalent) for a worktree directory preference. If specified, use it without asking.
|
||||
|
||||
### 2. Check CLAUDE.md
|
||||
4. **Default to `.worktrees/`.**
|
||||
|
||||
```bash
|
||||
grep -i "worktree.*director" CLAUDE.md 2>/dev/null
|
||||
```
|
||||
|
||||
**If preference specified:** Use it without asking.
|
||||
|
||||
### 3. Ask User
|
||||
|
||||
If no directory exists and no CLAUDE.md preference:
|
||||
|
||||
```
|
||||
No worktree directory found. Where should I create worktrees?
|
||||
|
||||
1. .worktrees/ (project-local, hidden)
|
||||
2. ~/.config/superpowers/worktrees/<project-name>/ (global location)
|
||||
|
||||
Which would you prefer?
|
||||
```
|
||||
|
||||
## Safety Verification
|
||||
|
||||
### For Project-Local Directories (.worktrees or worktrees)
|
||||
#### Safety Verification (project-local directories only)
|
||||
|
||||
**MUST verify directory is ignored before creating worktree:**
|
||||
|
||||
```bash
|
||||
# Check if directory is ignored (respects local, global, and system gitignore)
|
||||
git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null
|
||||
```
|
||||
|
||||
**If NOT ignored:**
|
||||
|
||||
Per Jesse's rule "Fix broken things immediately":
|
||||
1. Add appropriate line to .gitignore
|
||||
2. Commit the change
|
||||
3. Proceed with worktree creation
|
||||
**If NOT ignored:** Add to .gitignore, commit the change, then proceed.
|
||||
|
||||
**Why critical:** Prevents accidentally committing worktree contents to repository.
|
||||
|
||||
### For Global Directory (~/.config/superpowers/worktrees)
|
||||
Global directories (`~/.config/superpowers/worktrees/`) need no verification.
|
||||
|
||||
No .gitignore verification needed - outside project entirely.
|
||||
|
||||
## Creation Steps
|
||||
|
||||
### 1. Detect Project Name
|
||||
#### Create the Worktree
|
||||
|
||||
```bash
|
||||
project=$(basename "$(git rev-parse --show-toplevel)")
|
||||
```
|
||||
|
||||
### 2. Create Worktree
|
||||
# Determine path based on chosen location
|
||||
# For project-local: path="$LOCATION/$BRANCH_NAME"
|
||||
# For global: path="~/.config/superpowers/worktrees/$project/$BRANCH_NAME"
|
||||
|
||||
```bash
|
||||
# Determine full path
|
||||
case $LOCATION in
|
||||
.worktrees|worktrees)
|
||||
path="$LOCATION/$BRANCH_NAME"
|
||||
;;
|
||||
~/.config/superpowers/worktrees/*)
|
||||
path="~/.config/superpowers/worktrees/$project/$BRANCH_NAME"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create worktree with new branch
|
||||
git worktree add "$path" -b "$BRANCH_NAME"
|
||||
cd "$path"
|
||||
```
|
||||
|
||||
### 3. Run Project Setup
|
||||
#### Hooks Awareness
|
||||
|
||||
Git worktrees do not inherit the parent repo's hooks directory. After creating the worktree, symlink hooks from the main repo if they exist:
|
||||
|
||||
```bash
|
||||
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
|
||||
if [ -d "$MAIN_ROOT/.git/hooks" ]; then
|
||||
ln -sf "$MAIN_ROOT/.git/hooks" "$path/.git/hooks"
|
||||
fi
|
||||
```
|
||||
|
||||
This prevents pre-commit checks, linters, and other hooks from silently stopping when work moves to a worktree.
|
||||
|
||||
**Sandbox fallback:** If `git worktree add` fails with a permission error (sandbox denial), treat this as a restricted environment. Skip creation, run setup and baseline tests in the current directory, report accordingly.
|
||||
|
||||
## Step 3: Project Setup
|
||||
|
||||
Auto-detect and run appropriate setup:
|
||||
|
||||
@@ -117,23 +139,20 @@ if [ -f pyproject.toml ]; then poetry install; fi
|
||||
if [ -f go.mod ]; then go mod download; fi
|
||||
```
|
||||
|
||||
### 4. Verify Clean Baseline
|
||||
## Step 4: Verify Clean Baseline
|
||||
|
||||
Run tests to ensure worktree starts clean:
|
||||
Run tests to ensure workspace starts clean:
|
||||
|
||||
```bash
|
||||
# Examples - use project-appropriate command
|
||||
npm test
|
||||
cargo test
|
||||
pytest
|
||||
go test ./...
|
||||
# Use project-appropriate command
|
||||
npm test / cargo test / pytest / go test ./...
|
||||
```
|
||||
|
||||
**If tests fail:** Report failures, ask whether to proceed or investigate.
|
||||
|
||||
**If tests pass:** Report ready.
|
||||
|
||||
### 5. Report Location
|
||||
### Report
|
||||
|
||||
```
|
||||
Worktree ready at <full-path>
|
||||
@@ -145,16 +164,32 @@ Ready to implement <feature-name>
|
||||
|
||||
| Situation | Action |
|
||||
|-----------|--------|
|
||||
| Already in linked worktree | Skip creation (Step 0) |
|
||||
| In a submodule | Treat as normal repo (Step 0 guard) |
|
||||
| Native worktree tool available | Use it (Step 1a) |
|
||||
| No native tool | Git worktree fallback (Step 1b) |
|
||||
| `.worktrees/` exists | Use it (verify ignored) |
|
||||
| `worktrees/` exists | Use it (verify ignored) |
|
||||
| Both exist | Use `.worktrees/` |
|
||||
| Neither exists | Check CLAUDE.md → Ask user |
|
||||
| Neither exists | Check instruction file, then default `.worktrees/` |
|
||||
| Global path exists | Use it (backward compat) |
|
||||
| Directory not ignored | Add to .gitignore + commit |
|
||||
| Permission error on create | Sandbox fallback, work in place |
|
||||
| Tests fail during baseline | Report failures + ask |
|
||||
| No package.json/Cargo.toml | Skip dependency install |
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### Fighting the harness
|
||||
|
||||
- **Problem:** Using `git worktree add` when the platform already provides isolation
|
||||
- **Fix:** Step 0 detects existing isolation. Step 1a defers to native tools.
|
||||
|
||||
### Skipping detection
|
||||
|
||||
- **Problem:** Creating a nested worktree inside an existing one
|
||||
- **Fix:** Always run Step 0 before creating anything
|
||||
|
||||
### Skipping ignore verification
|
||||
|
||||
- **Problem:** Worktree contents get tracked, pollute git status
|
||||
@@ -163,55 +198,36 @@ Ready to implement <feature-name>
|
||||
### Assuming directory location
|
||||
|
||||
- **Problem:** Creates inconsistency, violates project conventions
|
||||
- **Fix:** Follow priority: existing > CLAUDE.md > ask
|
||||
- **Fix:** Follow priority: existing > instruction file > default
|
||||
|
||||
### Proceeding with failing tests
|
||||
|
||||
- **Problem:** Can't distinguish new bugs from pre-existing issues
|
||||
- **Fix:** Report failures, get explicit permission to proceed
|
||||
|
||||
### Hardcoding setup commands
|
||||
|
||||
- **Problem:** Breaks on projects using different tools
|
||||
- **Fix:** Auto-detect from project files (package.json, etc.)
|
||||
|
||||
## Example Workflow
|
||||
|
||||
```
|
||||
You: I'm using the using-git-worktrees skill to set up an isolated workspace.
|
||||
|
||||
[Check .worktrees/ - exists]
|
||||
[Verify ignored - git check-ignore confirms .worktrees/ is ignored]
|
||||
[Create worktree: git worktree add .worktrees/auth -b feature/auth]
|
||||
[Run npm install]
|
||||
[Run npm test - 47 passing]
|
||||
|
||||
Worktree ready at /Users/jesse/myproject/.worktrees/auth
|
||||
Tests passing (47 tests, 0 failures)
|
||||
Ready to implement auth feature
|
||||
```
|
||||
|
||||
## Red Flags
|
||||
|
||||
**Never:**
|
||||
- Create a worktree when Step 0 detects existing isolation
|
||||
- Use git commands when a native worktree tool is available
|
||||
- Create worktree without verifying it's ignored (project-local)
|
||||
- Skip baseline test verification
|
||||
- Proceed with failing tests without asking
|
||||
- Assume directory location when ambiguous
|
||||
- Skip CLAUDE.md check
|
||||
|
||||
**Always:**
|
||||
- Follow directory priority: existing > CLAUDE.md > ask
|
||||
- Run Step 0 detection first
|
||||
- Prefer native tools over git fallback
|
||||
- Follow directory priority: existing > instruction file > default
|
||||
- Verify directory is ignored for project-local
|
||||
- Auto-detect and run project setup
|
||||
- Verify clean test baseline
|
||||
- Symlink hooks after creating worktree via 1b
|
||||
|
||||
## Integration
|
||||
|
||||
**Called by:**
|
||||
- **brainstorming** (Phase 4) - REQUIRED when design is approved and implementation follows
|
||||
- **subagent-driven-development** - REQUIRED before executing any tasks
|
||||
- **executing-plans** - REQUIRED before executing any tasks
|
||||
- **subagent-driven-development** - Ensures isolated workspace (creates one or verifies existing)
|
||||
- **executing-plans** - Ensures isolated workspace (creates one or verifies existing)
|
||||
- Any skill needing isolated workspace
|
||||
|
||||
**Pairs with:**
|
||||
|
||||
Reference in New Issue
Block a user