docs: add git-worktree suite, security kill switch, update reference.yaml + CC releases
- Git worktree commands: overhauled main + 3 new (status, remove, clean) - Security hardening: AI Kill Switch & Containment Architecture (§3.5) - DevOps SRE: cross-reference to security-hardening for AI incidents - CC releases: v2.1.43-v2.1.44 tracking - reference.yaml: 12 new entries, evaluations count 67 → 74 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
70c6c34658
commit
0d6a0c656e
11 changed files with 821 additions and 64 deletions
240
examples/commands/git-worktree-clean.md
Normal file
240
examples/commands/git-worktree-clean.md
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
---
|
||||
name: git-worktree-clean
|
||||
description: "Clean up stale git worktrees with merged branch detection and disk usage report"
|
||||
---
|
||||
|
||||
# Git Worktree Clean
|
||||
|
||||
Batch cleanup of stale git worktrees. Safely removes merged branches, reports disk usage, and handles unmerged branches interactively.
|
||||
|
||||
**Core principle:** Auto-clean merged worktrees, interactive review for unmerged, always report what was reclaimed.
|
||||
|
||||
**Part of:** [Worktree Lifecycle Suite](./git-worktree.md) | [`/git-worktree`](./git-worktree.md) | [`/git-worktree-status`](./git-worktree-status.md) | [`/git-worktree-remove`](./git-worktree-remove.md)
|
||||
|
||||
## Process
|
||||
|
||||
1. **List All Worktrees**: `git worktree list`
|
||||
2. **Classify Each**: merged vs unmerged vs protected
|
||||
3. **Calculate Disk Usage**: Per-worktree size
|
||||
4. **Auto Mode**: Remove all merged worktrees (safe)
|
||||
5. **Interactive Mode**: Review unmerged worktrees one by one
|
||||
6. **Database Cleanup Reminder**: List DB branches to clean
|
||||
7. **Report**: Summary of actions taken and space reclaimed
|
||||
|
||||
## Flags
|
||||
|
||||
| Flag | Effect |
|
||||
|------|--------|
|
||||
| `--dry-run` | Preview what would be cleaned, no changes |
|
||||
| `--all` | Include unmerged worktrees (interactive confirmation each) |
|
||||
| `--force` | Remove all worktrees without confirmation (dangerous) |
|
||||
|
||||
## Worktree Discovery
|
||||
|
||||
```bash
|
||||
# Get main branch name
|
||||
MAIN_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
|
||||
MAIN_BRANCH=${MAIN_BRANCH:-main}
|
||||
|
||||
# Protected branches (never auto-clean)
|
||||
PROTECTED="main master develop staging production"
|
||||
|
||||
# List all worktrees (skip main working tree)
|
||||
git worktree list --porcelain | while read line; do
|
||||
# Parse worktree path and branch
|
||||
# Skip the main worktree (first entry)
|
||||
done
|
||||
```
|
||||
|
||||
## Classification
|
||||
|
||||
```bash
|
||||
for WORKTREE in $WORKTREES; do
|
||||
BRANCH=$(git -C "$WORKTREE" rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Skip protected
|
||||
if echo "$PROTECTED" | grep -qw "$BRANCH"; then
|
||||
echo "PROTECTED: $BRANCH (skipped)"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check merge status
|
||||
if git merge-base --is-ancestor "$BRANCH" "$MAIN_BRANCH" 2>/dev/null; then
|
||||
echo "MERGED: $BRANCH → safe to remove"
|
||||
MERGED_LIST="$MERGED_LIST $WORKTREE"
|
||||
else
|
||||
echo "UNMERGED: $BRANCH → requires review"
|
||||
UNMERGED_LIST="$UNMERGED_LIST $WORKTREE"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
## Disk Usage Calculation
|
||||
|
||||
```bash
|
||||
for WORKTREE in $ALL_WORKTREES; do
|
||||
# Calculate size excluding symlinked node_modules
|
||||
SIZE=$(du -sh --exclude='node_modules' "$WORKTREE" 2>/dev/null | cut -f1)
|
||||
# Or on macOS:
|
||||
SIZE=$(du -sh -I 'node_modules' "$WORKTREE" 2>/dev/null | cut -f1)
|
||||
echo " $WORKTREE: $SIZE"
|
||||
done
|
||||
```
|
||||
|
||||
## Dry Run Mode
|
||||
|
||||
```bash
|
||||
# --dry-run: show what would happen without making changes
|
||||
|
||||
echo "=== Dry Run ==="
|
||||
echo ""
|
||||
echo "Would remove (merged):"
|
||||
for WT in $MERGED_LIST; do
|
||||
echo " $WT ($BRANCH) - $SIZE"
|
||||
done
|
||||
echo ""
|
||||
echo "Would ask about (unmerged):"
|
||||
for WT in $UNMERGED_LIST; do
|
||||
echo " $WT ($BRANCH) - $SIZE - last commit: $(git log -1 --format='%s' $BRANCH)"
|
||||
done
|
||||
echo ""
|
||||
echo "Total space to reclaim: $TOTAL_SIZE"
|
||||
echo ""
|
||||
echo "Run without --dry-run to execute."
|
||||
```
|
||||
|
||||
## Auto Mode (Default)
|
||||
|
||||
**Only removes merged worktrees. Safe by default.**
|
||||
|
||||
```bash
|
||||
echo "Cleaning merged worktrees..."
|
||||
|
||||
for WORKTREE in $MERGED_LIST; do
|
||||
BRANCH=$(git -C "$WORKTREE" rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Remove worktree
|
||||
git worktree remove "$WORKTREE"
|
||||
|
||||
# Delete local branch
|
||||
git branch -d "$BRANCH" 2>/dev/null
|
||||
|
||||
# Delete remote branch
|
||||
git push origin --delete "$BRANCH" 2>/dev/null
|
||||
|
||||
echo " Removed: $WORKTREE ($BRANCH)"
|
||||
done
|
||||
|
||||
# Report unmerged (not touched)
|
||||
if [ -n "$UNMERGED_LIST" ]; then
|
||||
echo ""
|
||||
echo "Unmerged worktrees (kept):"
|
||||
for WT in $UNMERGED_LIST; do
|
||||
echo " $WT - use /git-worktree-remove or --all to review"
|
||||
done
|
||||
fi
|
||||
```
|
||||
|
||||
## Interactive Mode (--all)
|
||||
|
||||
**Reviews unmerged worktrees one by one:**
|
||||
|
||||
```bash
|
||||
for WORKTREE in $UNMERGED_LIST; do
|
||||
BRANCH=$(git -C "$WORKTREE" rev-parse --abbrev-ref HEAD)
|
||||
LAST_COMMIT=$(git log -1 --format='%h %s (%cr)' "$BRANCH")
|
||||
AHEAD=$(git rev-list --count "$MAIN_BRANCH".."$BRANCH")
|
||||
|
||||
echo ""
|
||||
echo "Unmerged: $WORKTREE"
|
||||
echo " Branch: $BRANCH ($AHEAD commits ahead of $MAIN_BRANCH)"
|
||||
echo " Last commit: $LAST_COMMIT"
|
||||
echo " Size: $SIZE"
|
||||
echo ""
|
||||
echo " [r]emove [k]eep [s]kip remaining"
|
||||
|
||||
# Wait for user decision per worktree
|
||||
done
|
||||
```
|
||||
|
||||
## Report Format
|
||||
|
||||
**After cleanup:**
|
||||
|
||||
```
|
||||
=== Worktree Cleanup Report ===
|
||||
|
||||
Removed (merged):
|
||||
.worktrees/feat/auth (feat/auth) - 2.3 MB
|
||||
.worktrees/fix/login-bug (fix/login-bug) - 1.1 MB
|
||||
.worktrees/chore/deps-update (chore/deps-update) - 0.8 MB
|
||||
|
||||
Kept (unmerged):
|
||||
.worktrees/feat/experimental (feat/experimental) - 4.2 MB
|
||||
Last commit: a1b2c3d "WIP: new auth flow" (3 days ago)
|
||||
|
||||
Kept (protected):
|
||||
.worktrees/develop (develop)
|
||||
|
||||
Space reclaimed: 4.2 MB
|
||||
Worktrees remaining: 2
|
||||
References pruned: yes
|
||||
|
||||
DB branches to clean:
|
||||
neonctl branches delete feat-auth
|
||||
neonctl branches delete fix-login-bug
|
||||
neonctl branches delete chore-deps-update
|
||||
```
|
||||
|
||||
**Dry run report:**
|
||||
|
||||
```
|
||||
=== Dry Run - No Changes Made ===
|
||||
|
||||
Would remove (3 merged):
|
||||
.worktrees/feat/auth - 2.3 MB
|
||||
.worktrees/fix/login-bug - 1.1 MB
|
||||
.worktrees/chore/deps-update - 0.8 MB
|
||||
|
||||
Would keep (1 unmerged):
|
||||
.worktrees/feat/experimental - 4.2 MB
|
||||
|
||||
Would keep (1 protected):
|
||||
.worktrees/develop
|
||||
|
||||
Potential space savings: 4.2 MB
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Situation | Action |
|
||||
|-----------|--------|
|
||||
| Default (no flags) | Remove merged worktrees only |
|
||||
| `--dry-run` | Preview without changes |
|
||||
| `--all` | Merged (auto) + unmerged (interactive) |
|
||||
| `--force` | Remove everything except protected |
|
||||
| Protected branch | Always kept |
|
||||
| Merged branch | Auto-removed |
|
||||
| Unmerged branch | Kept (default) or interactive (--all) |
|
||||
| DB branches detected | Reminder with exact commands |
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
**Running `--force` without `--dry-run` first**
|
||||
- Always preview with `--dry-run` before force-cleaning
|
||||
|
||||
**Forgetting DB branch cleanup**
|
||||
- Worktree cleanup doesn't auto-delete DB branches. Follow the reminder commands.
|
||||
|
||||
**Not running cleanup regularly**
|
||||
- Stale worktrees accumulate disk space. Run `/git-worktree-clean --dry-run` weekly.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/git-worktree-clean
|
||||
/git-worktree-clean --dry-run
|
||||
/git-worktree-clean --all
|
||||
```
|
||||
|
||||
Flags: $ARGUMENTS
|
||||
189
examples/commands/git-worktree-remove.md
Normal file
189
examples/commands/git-worktree-remove.md
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
---
|
||||
name: git-worktree-remove
|
||||
description: "Safely remove a git worktree with branch cleanup and safety checks"
|
||||
---
|
||||
|
||||
# Git Worktree Remove
|
||||
|
||||
Safely remove a single git worktree with branch cleanup, merge verification, and database branch teardown.
|
||||
|
||||
**Core principle:** Safety checks first, then clean removal of worktree + branch + DB resources.
|
||||
|
||||
**Part of:** [Worktree Lifecycle Suite](./git-worktree.md) | [`/git-worktree`](./git-worktree.md) | [`/git-worktree-status`](./git-worktree-status.md) | [`/git-worktree-clean`](./git-worktree-clean.md)
|
||||
|
||||
## Process
|
||||
|
||||
1. **Validate Target**: Identify worktree to remove
|
||||
2. **Safety Check**: Protect main/develop branches
|
||||
3. **Check Merge Status**: Warn if branch has unmerged changes
|
||||
4. **Check Uncommitted Changes**: Warn if worktree has dirty state
|
||||
5. **Remove Worktree**: `git worktree remove`
|
||||
6. **Delete Local Branch**: `git branch -d` (or `-D` with confirmation)
|
||||
7. **Delete Remote Branch**: `git push origin --delete` (with confirmation)
|
||||
8. **Database Cleanup Reminder**: Suggest DB branch deletion if applicable
|
||||
9. **Prune References**: `git worktree prune`
|
||||
|
||||
## Safety Checks
|
||||
|
||||
### Protected Branches
|
||||
|
||||
```bash
|
||||
# Never remove worktrees for these branches (configurable)
|
||||
PROTECTED_BRANCHES="main master develop staging production"
|
||||
|
||||
if echo "$PROTECTED_BRANCHES" | grep -qw "$BRANCH"; then
|
||||
echo "BLOCKED: Cannot remove worktree for protected branch '$BRANCH'"
|
||||
echo "Protected branches: $PROTECTED_BRANCHES"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### Uncommitted Changes
|
||||
|
||||
```bash
|
||||
cd "$WORKTREE_PATH"
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "WARNING: Worktree has uncommitted changes:"
|
||||
git status --short
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " 1. Commit changes first"
|
||||
echo " 2. Force remove (--force)"
|
||||
echo " 3. Cancel"
|
||||
# Wait for user decision
|
||||
fi
|
||||
```
|
||||
|
||||
### Merge Status
|
||||
|
||||
```bash
|
||||
# Check if branch is merged into main
|
||||
MAIN_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')
|
||||
|
||||
if git merge-base --is-ancestor "$BRANCH" "$MAIN_BRANCH" 2>/dev/null; then
|
||||
echo "Branch '$BRANCH' is merged into $MAIN_BRANCH. Safe to delete."
|
||||
MERGED=true
|
||||
else
|
||||
echo "WARNING: Branch '$BRANCH' is NOT merged into $MAIN_BRANCH."
|
||||
echo "You may lose work if you delete this branch."
|
||||
MERGED=false
|
||||
fi
|
||||
```
|
||||
|
||||
## Removal Steps
|
||||
|
||||
```bash
|
||||
# 1. Remove the worktree
|
||||
git worktree remove "$WORKTREE_PATH"
|
||||
# If dirty state and user confirmed force:
|
||||
# git worktree remove --force "$WORKTREE_PATH"
|
||||
|
||||
# 2. Delete local branch
|
||||
if [ "$MERGED" = true ]; then
|
||||
git branch -d "$BRANCH"
|
||||
else
|
||||
echo "Delete unmerged branch '$BRANCH'? (requires confirmation)"
|
||||
# On confirmation:
|
||||
git branch -D "$BRANCH"
|
||||
fi
|
||||
|
||||
# 3. Delete remote branch (with confirmation)
|
||||
if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then
|
||||
echo "Delete remote branch 'origin/$BRANCH'?"
|
||||
# On confirmation:
|
||||
git push origin --delete "$BRANCH"
|
||||
fi
|
||||
|
||||
# 4. Prune stale references
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
## Database Branch Cleanup
|
||||
|
||||
**After worktree removal, remind about associated database branches:**
|
||||
|
||||
```bash
|
||||
# Detect database provider (same logic as /git-worktree)
|
||||
if [ -f ".env" ] && grep -q "neon" ".env"; then
|
||||
echo ""
|
||||
echo "DB Cleanup: neonctl branches delete $BRANCH_SLUG"
|
||||
elif [ -f ".pscale.yml" ]; then
|
||||
echo ""
|
||||
DB_NAME=$(grep 'database:' .pscale.yml | awk '{print $2}')
|
||||
echo "DB Cleanup: pscale branch delete $DB_NAME $BRANCH_SLUG"
|
||||
elif [ -f ".env" ] && grep -q "postgresql" ".env"; then
|
||||
echo ""
|
||||
echo "DB Cleanup: psql \$DATABASE_URL -c \"DROP SCHEMA ${BRANCH_SLUG} CASCADE;\""
|
||||
fi
|
||||
```
|
||||
|
||||
## Report Format
|
||||
|
||||
**Successful removal (merged branch):**
|
||||
|
||||
```
|
||||
Removed worktree: .worktrees/feat/auth
|
||||
Worktree directory: deleted
|
||||
Local branch feat/auth: deleted (was merged)
|
||||
Remote branch origin/feat/auth: deleted
|
||||
References: pruned
|
||||
|
||||
DB reminder: neonctl branches delete feat-auth
|
||||
```
|
||||
|
||||
**Removal with warnings (unmerged branch):**
|
||||
|
||||
```
|
||||
Removed worktree: .worktrees/feat/experimental
|
||||
Worktree directory: deleted
|
||||
Local branch feat/experimental: deleted (was NOT merged - forced)
|
||||
Remote branch: no remote branch found
|
||||
References: pruned
|
||||
|
||||
WARNING: Branch was not merged. Changes may be lost.
|
||||
Last commit: a1b2c3d "WIP: experimental auth flow"
|
||||
```
|
||||
|
||||
## Flags
|
||||
|
||||
| Flag | Effect |
|
||||
|------|--------|
|
||||
| `--force` | Skip uncommitted changes warning |
|
||||
| `--keep-branch` | Remove worktree but keep the branch |
|
||||
| `--keep-remote` | Don't delete remote branch |
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Situation | Action |
|
||||
|-----------|--------|
|
||||
| Branch is merged | Safe delete (branch -d) |
|
||||
| Branch is unmerged | Warn + require confirmation (branch -D) |
|
||||
| Uncommitted changes | Warn + offer force/cancel |
|
||||
| Protected branch (main/develop) | Block removal |
|
||||
| Remote branch exists | Ask to delete remote |
|
||||
| DB branch detected | Remind with exact command |
|
||||
| Stale references | Auto-prune |
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
**Removing worktree for main/develop**
|
||||
- Always blocked by safety check. Reconfigure protected branches if needed.
|
||||
|
||||
**Deleting unmerged branch without checking**
|
||||
- Always verify merge status. Unmerged branches require explicit `--force` or `-D`.
|
||||
|
||||
**Forgetting database branch cleanup**
|
||||
- Leaves orphaned DB branches consuming resources. Command reminds automatically.
|
||||
|
||||
**Using `rm -rf` instead of `git worktree remove`**
|
||||
- Leaves stale worktree references in `.git/worktrees/`. Always use git commands.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/git-worktree-remove feat/auth
|
||||
/git-worktree-remove fix/login-bug --force
|
||||
/git-worktree-remove refactor/db --keep-branch
|
||||
```
|
||||
|
||||
Branch or worktree path: $ARGUMENTS
|
||||
164
examples/commands/git-worktree-status.md
Normal file
164
examples/commands/git-worktree-status.md
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
---
|
||||
name: git-worktree-status
|
||||
description: "Check status of background verification tasks running in a git worktree"
|
||||
---
|
||||
|
||||
# Git Worktree Status
|
||||
|
||||
Check background verification tasks (type check, tests, build) launched by `/git-worktree`.
|
||||
|
||||
**Core principle:** Non-blocking feedback on worktree health without interrupting development flow.
|
||||
|
||||
**Part of:** [Worktree Lifecycle Suite](./git-worktree.md) | [`/git-worktree`](./git-worktree.md) | [`/git-worktree-remove`](./git-worktree-remove.md) | [`/git-worktree-clean`](./git-worktree-clean.md)
|
||||
|
||||
## Process
|
||||
|
||||
1. **Detect Current Worktree**: Verify we're inside a git worktree
|
||||
2. **Check Log Files**: Read `.worktree-logs/` for background task results
|
||||
3. **Parse Results**: Extract pass/fail counts, errors
|
||||
4. **Report Status**: Color-coded summary with actionable next steps
|
||||
|
||||
## Worktree Detection
|
||||
|
||||
```bash
|
||||
# Check if inside a worktree (not main repo)
|
||||
git rev-parse --git-common-dir 2>/dev/null | grep -q "\.git/worktrees" || {
|
||||
echo "Not inside a worktree. Use from a worktree directory."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get worktree info
|
||||
WORKTREE_PATH=$(git rev-parse --show-toplevel)
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
MAIN_REPO=$(git rev-parse --git-common-dir | sed 's|/\.git/worktrees/.*||')
|
||||
```
|
||||
|
||||
## Background Task Checks
|
||||
|
||||
### Type Check Status
|
||||
|
||||
```bash
|
||||
LOG=".worktree-logs/typecheck.log"
|
||||
|
||||
if [ -f "$LOG" ]; then
|
||||
if grep -q "error TS" "$LOG"; then
|
||||
ERROR_COUNT=$(grep -c "error TS" "$LOG")
|
||||
echo "Type check: FAIL ($ERROR_COUNT errors)"
|
||||
# Show first 5 errors
|
||||
grep "error TS" "$LOG" | head -5
|
||||
else
|
||||
echo "Type check: PASS"
|
||||
fi
|
||||
elif pgrep -f "tsc --noEmit" > /dev/null; then
|
||||
echo "Type check: RUNNING..."
|
||||
else
|
||||
echo "Type check: NOT RUN"
|
||||
fi
|
||||
```
|
||||
|
||||
### Test Status
|
||||
|
||||
```bash
|
||||
LOG=".worktree-logs/tests.log"
|
||||
|
||||
if [ -f "$LOG" ]; then
|
||||
if grep -q '"numFailedTests":0' "$LOG"; then
|
||||
TOTAL=$(grep -o '"numTotalTests":[0-9]*' "$LOG" | cut -d: -f2)
|
||||
echo "Tests: PASS ($TOTAL tests)"
|
||||
else
|
||||
FAILED=$(grep -o '"numFailedTests":[0-9]*' "$LOG" | cut -d: -f2)
|
||||
echo "Tests: FAIL ($FAILED failures)"
|
||||
# Show failed test names
|
||||
grep '"fullName"' "$LOG" | head -5
|
||||
fi
|
||||
elif pgrep -f "vitest run" > /dev/null; then
|
||||
echo "Tests: RUNNING..."
|
||||
else
|
||||
echo "Tests: NOT RUN"
|
||||
fi
|
||||
```
|
||||
|
||||
### Build Status
|
||||
|
||||
```bash
|
||||
LOG=".worktree-logs/build.log"
|
||||
|
||||
if [ -f "$LOG" ]; then
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Build: PASS"
|
||||
else
|
||||
echo "Build: FAIL"
|
||||
tail -10 "$LOG"
|
||||
fi
|
||||
elif pgrep -f "cargo build\|next build\|go build" > /dev/null; then
|
||||
echo "Build: RUNNING..."
|
||||
else
|
||||
echo "Build: NOT RUN"
|
||||
fi
|
||||
```
|
||||
|
||||
## Report Format
|
||||
|
||||
```
|
||||
Worktree Status: .worktrees/feat/auth
|
||||
Branch: feat/auth (from main, 3 commits ahead)
|
||||
|
||||
Checks:
|
||||
Type check: PASS
|
||||
Tests: PASS (142 tests)
|
||||
Build: NOT RUN
|
||||
|
||||
Dependencies: symlinked from main
|
||||
Disk usage: 2.3 MB (excl. node_modules)
|
||||
|
||||
Log files: .worktree-logs/
|
||||
```
|
||||
|
||||
**If failures detected:**
|
||||
|
||||
```
|
||||
Worktree Status: .worktrees/feat/auth
|
||||
Branch: feat/auth (from main, 3 commits ahead)
|
||||
|
||||
Checks:
|
||||
Type check: FAIL (3 errors)
|
||||
src/auth.ts:42 - error TS2345: Argument of type 'string' is not assignable
|
||||
src/auth.ts:67 - error TS2304: Cannot find name 'AuthConfig'
|
||||
src/middleware.ts:12 - error TS7006: Parameter 'req' implicitly has an 'any' type
|
||||
Tests: FAIL (2 failures)
|
||||
auth.test.ts > should validate token
|
||||
auth.test.ts > should reject expired token
|
||||
Build: NOT RUN
|
||||
|
||||
Action: Fix type errors before proceeding. Run `npx tsc --noEmit` for full output.
|
||||
```
|
||||
|
||||
## Log Management
|
||||
|
||||
```bash
|
||||
# Clean old logs (useful for re-running checks)
|
||||
rm -rf .worktree-logs/*.log
|
||||
|
||||
# Re-run all checks
|
||||
npx tsc --noEmit > .worktree-logs/typecheck.log 2>&1 &
|
||||
npx vitest run --reporter=json > .worktree-logs/tests.log 2>&1 &
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Situation | Output |
|
||||
|-----------|--------|
|
||||
| All checks pass | Green status, ready to work |
|
||||
| Checks still running | "RUNNING..." with PID |
|
||||
| Type errors found | Error count + first 5 errors |
|
||||
| Test failures | Failure count + failed test names |
|
||||
| No logs found | "NOT RUN" (use `--fast` or logs deleted) |
|
||||
| Not in worktree | Error message with instructions |
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/git-worktree-status
|
||||
```
|
||||
|
||||
No arguments needed. Run from inside any worktree directory.
|
||||
|
|
@ -7,18 +7,49 @@ description: "Create isolated git worktrees for feature development without swit
|
|||
|
||||
Create isolated git worktrees for feature development without switching branches.
|
||||
|
||||
**Core principle:** Systematic directory selection + safety verification = reliable isolation.
|
||||
**Core principle:** Smart directory selection + symlink optimization + background verification = fast, reliable isolation.
|
||||
|
||||
**Requires:** Git 2.5.0+ (July 2015)
|
||||
|
||||
**Companion commands:** [`/git-worktree-status`](./git-worktree-status.md) | [`/git-worktree-remove`](./git-worktree-remove.md) | [`/git-worktree-clean`](./git-worktree-clean.md)
|
||||
|
||||
## Process
|
||||
|
||||
1. **Check Existing Directories**: `.worktrees/` or `worktrees/`
|
||||
2. **Verify .gitignore**: Ensure worktree dir is ignored
|
||||
3. **Create Worktree**: `git worktree add`
|
||||
4. **Detect Database Provider**: Check for DB branching capability
|
||||
5. **Suggest Database Branch**: Remind user with exact commands
|
||||
6. **Install Dependencies**: Auto-detect package manager
|
||||
7. **Run Baseline Tests**: Verify clean state
|
||||
8. **Report Location**: Confirm ready
|
||||
1. **Validate Branch Name**: Check naming convention and conflicts
|
||||
2. **Check Existing Directories**: `.worktrees/` or `worktrees/`
|
||||
3. **Verify .gitignore**: Ensure worktree dir is ignored
|
||||
4. **Create Worktree**: `git worktree add`
|
||||
5. **Symlink Dependencies**: Reuse `node_modules/` from main worktree
|
||||
6. **Detect Database Provider**: Check for DB branching capability
|
||||
7. **Install Dependencies**: Auto-detect package manager (if not symlinking)
|
||||
8. **Run Background Verification**: Type check + tests in background
|
||||
9. **Report Location**: Confirm ready with status
|
||||
|
||||
## Flags
|
||||
|
||||
| Flag | Effect |
|
||||
|------|--------|
|
||||
| `--fast` | Skip dependency install and baseline tests |
|
||||
| `--isolated` | Fresh `node_modules` install (no symlink) |
|
||||
| `--skip-install` | Skip dependency install, keep baseline tests |
|
||||
|
||||
## Branch Name Validation
|
||||
|
||||
```bash
|
||||
# Auto-prefix based on naming convention
|
||||
# "auth" → "feat/auth" (default prefix)
|
||||
# "fix/login-bug" → kept as-is
|
||||
# "refactor/db-layer" → kept as-is
|
||||
|
||||
# Accepted prefixes: feat/, fix/, refactor/, chore/, docs/, test/, perf/
|
||||
# If no prefix → default to feat/
|
||||
|
||||
# Reject invalid characters
|
||||
echo "$BRANCH_NAME" | grep -qE '^[a-zA-Z0-9/_-]+$' || exit 1
|
||||
|
||||
# Check branch doesn't already exist
|
||||
git show-ref --verify --quiet "refs/heads/$BRANCH_NAME" && echo "Branch already exists" && exit 1
|
||||
```
|
||||
|
||||
## Directory Selection
|
||||
|
||||
|
|
@ -66,11 +97,35 @@ git worktree add .worktrees/$BRANCH_NAME -b $BRANCH_NAME
|
|||
cd .worktrees/$BRANCH_NAME
|
||||
```
|
||||
|
||||
## Auto-Detect Setup
|
||||
## Dependency Optimization (Node.js)
|
||||
|
||||
**Default behavior:** Symlink `node_modules` from main worktree to avoid duplicate installs (~30s saved).
|
||||
|
||||
```bash
|
||||
# Node.js
|
||||
if [ -f package.json ]; then pnpm install; fi
|
||||
# Symlink node_modules (default, unless --isolated)
|
||||
if [ -d "../../node_modules" ] && [ ! "$ISOLATED" = true ]; then
|
||||
ln -s "$(cd ../.. && pwd)/node_modules" node_modules
|
||||
echo "Symlinked node_modules from main worktree"
|
||||
fi
|
||||
|
||||
# With --isolated: fresh install
|
||||
if [ "$ISOLATED" = true ]; then
|
||||
pnpm install # or npm/yarn based on lockfile detection
|
||||
fi
|
||||
```
|
||||
|
||||
**When to use `--isolated`:**
|
||||
- Schema changes requiring different package versions
|
||||
- Testing dependency upgrades
|
||||
- Debugging `node_modules` issues
|
||||
|
||||
## Auto-Detect Setup (Multi-Stack)
|
||||
|
||||
```bash
|
||||
# Node.js (if not symlinked)
|
||||
if [ -f package.json ] && [ ! -L node_modules ]; then
|
||||
pnpm install # Detect from lockfile: pnpm-lock.yaml / yarn.lock / package-lock.json
|
||||
fi
|
||||
|
||||
# Rust
|
||||
if [ -f Cargo.toml ]; then cargo build; fi
|
||||
|
|
@ -83,30 +138,44 @@ if [ -f pyproject.toml ]; then poetry install; fi
|
|||
if [ -f go.mod ]; then go mod download; fi
|
||||
```
|
||||
|
||||
## Baseline Verification
|
||||
## Background Verification
|
||||
|
||||
**Instead of blocking on full test suite, run verification in background:**
|
||||
|
||||
```bash
|
||||
# Run tests to verify clean state
|
||||
pnpm test # Node.js
|
||||
cargo test # Rust
|
||||
pytest # Python
|
||||
go test ./... # Go
|
||||
# Create log directory
|
||||
mkdir -p .worktree-logs
|
||||
|
||||
# Background type check (Node.js)
|
||||
if [ -f tsconfig.json ]; then
|
||||
npx tsc --noEmit > .worktree-logs/typecheck.log 2>&1 &
|
||||
echo "Type check running in background (check with /git-worktree-status)"
|
||||
fi
|
||||
|
||||
# Background test run
|
||||
if [ -f package.json ]; then
|
||||
npx vitest run --reporter=json > .worktree-logs/tests.log 2>&1 &
|
||||
echo "Tests running in background (check with /git-worktree-status)"
|
||||
fi
|
||||
```
|
||||
|
||||
**If tests fail:** Report failures, ask whether to proceed.
|
||||
**If tests pass:** Report ready.
|
||||
**With `--fast`:** Skip all verification.
|
||||
|
||||
## Final Report
|
||||
|
||||
```
|
||||
Worktree ready at <full-path>
|
||||
Tests passing (<N> tests, 0 failures)
|
||||
Branch: feat/auth (created from main)
|
||||
Dependencies: symlinked from main worktree
|
||||
Background checks: type check + tests running
|
||||
Check status: /git-worktree-status
|
||||
|
||||
Ready to implement <feature-name>
|
||||
```
|
||||
|
||||
## Database Branch Suggestion
|
||||
|
||||
**After worktree creation, command detects database provider and suggests isolation.**
|
||||
**After worktree creation, detect database provider and suggest isolation.**
|
||||
|
||||
### Quick Command Reference
|
||||
|
||||
|
|
@ -120,9 +189,9 @@ Ready to implement <feature-name>
|
|||
**Example output:**
|
||||
|
||||
```
|
||||
✅ Worktree created at .worktrees/feature-auth
|
||||
Worktree created at .worktrees/feat/auth
|
||||
|
||||
💡 DB Isolation: neonctl branches create --name feature-auth --parent main
|
||||
DB Isolation: neonctl branches create --name feat-auth --parent main
|
||||
Then update .env with new DATABASE_URL
|
||||
Full guide: ../workflows/database-branch-setup.md
|
||||
```
|
||||
|
|
@ -139,16 +208,16 @@ Ready to implement <feature-name>
|
|||
**/.claude/settings.local.json
|
||||
```
|
||||
|
||||
**Why:** Without this, `.env` files won't be copied to worktrees → Claude sessions fail.
|
||||
**Why:** Without this, `.env` files won't be copied to worktrees.
|
||||
|
||||
### When to Create Database Branch
|
||||
|
||||
| Scenario | Create Branch? |
|
||||
|----------|---------------|
|
||||
| Schema migrations | ✅ Yes |
|
||||
| Data model refactoring | ✅ Yes |
|
||||
| Bug fix (no schema change) | ❌ No |
|
||||
| Performance experiments | ✅ Yes |
|
||||
| Schema migrations | Yes |
|
||||
| Data model refactoring | Yes |
|
||||
| Bug fix (no schema change) | No |
|
||||
| Performance experiments | Yes |
|
||||
|
||||
**See:** [Database Branch Setup Guide](../workflows/database-branch-setup.md) for complete workflows.
|
||||
|
||||
|
|
@ -159,12 +228,15 @@ Ready to implement <feature-name>
|
|||
| `.worktrees/` exists | Use it (verify .gitignore) |
|
||||
| `worktrees/` exists | Use it (verify .gitignore) |
|
||||
| Both exist | Use `.worktrees/` |
|
||||
| Neither exists | Check CLAUDE.md → Ask user |
|
||||
| Neither exists | Check CLAUDE.md, then ask user |
|
||||
| Not in .gitignore | Add + commit immediately |
|
||||
| No branch prefix | Auto-prefix with `feat/` |
|
||||
| Node.js project | Symlink `node_modules` by default |
|
||||
| `--fast` flag | Skip install + tests |
|
||||
| `--isolated` flag | Fresh `node_modules` install |
|
||||
| Neon detected | Suggest `neonctl branches create` |
|
||||
| PlanetScale detected | Suggest `pscale branch create` |
|
||||
| No .worktreeinclude | Create with `.env` pattern |
|
||||
| Tests fail | Report + ask to proceed |
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
|
|
@ -174,8 +246,8 @@ Ready to implement <feature-name>
|
|||
**Assuming directory location**
|
||||
- Follow priority: existing > CLAUDE.md > ask
|
||||
|
||||
**Proceeding with failing tests**
|
||||
- Can't distinguish new bugs from pre-existing
|
||||
**Installing full node_modules in every worktree**
|
||||
- Wastes disk and time. Use symlink by default, `--isolated` only when needed
|
||||
|
||||
**Not copying .env to worktree**
|
||||
- Symptom: Claude fails with "DATABASE_URL not found"
|
||||
|
|
@ -185,34 +257,13 @@ Ready to implement <feature-name>
|
|||
- Symptom: Migration conflicts, broken dev environment
|
||||
- Fix: Create database branch before modifying schema
|
||||
|
||||
## Cleanup (After Work Complete)
|
||||
|
||||
```bash
|
||||
# 1. Remove git worktree
|
||||
git worktree remove .worktrees/$BRANCH_NAME
|
||||
|
||||
# Or force if uncommitted changes
|
||||
git worktree remove --force .worktrees/$BRANCH_NAME
|
||||
|
||||
# 2. If you created a database branch, delete it
|
||||
# Neon:
|
||||
neonctl branches delete $BRANCH_NAME
|
||||
|
||||
# PlanetScale:
|
||||
pscale branch delete <database-name> $BRANCH_NAME
|
||||
|
||||
# Local schema:
|
||||
psql $DATABASE_URL -c "DROP SCHEMA ${BRANCH_NAME/\//_} CASCADE;"
|
||||
|
||||
# 3. Prune stale references
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/git-worktree feature/auth
|
||||
/git-worktree auth
|
||||
/git-worktree fix/session-bug
|
||||
/git-worktree feature/new-api --fast
|
||||
/git-worktree refactor/db-layer --isolated
|
||||
```
|
||||
|
||||
Branch name: $ARGUMENTS
|
||||
Loading…
Add table
Add a link
Reference in a new issue