Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "git-worktrees",
|
||||
"description": "Manage Git worktrees for parallel Claude Code development. Use this skill when engineers ask to 'create a worktree', 'run parallel Claude sessions', 'work on multiple features simultaneously', or need help with worktree management.",
|
||||
"version": "0.0.0-2025.11.28",
|
||||
"author": {
|
||||
"name": "James Rochabrun",
|
||||
"email": "jamesrochabrun@gmail.com"
|
||||
},
|
||||
"skills": [
|
||||
"./skills/git-worktrees"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# git-worktrees
|
||||
|
||||
Manage Git worktrees for parallel Claude Code development. Use this skill when engineers ask to 'create a worktree', 'run parallel Claude sessions', 'work on multiple features simultaneously', or need help with worktree management.
|
||||
72
plugin.lock.json
Normal file
72
plugin.lock.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:jamesrochabrun/skills:git-worktrees",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "a47915ea9987b45f60bdd6f9999272e41c6aee5c",
|
||||
"treeHash": "b3894f41c934467d8114c180d756c70bbcb8cf4c8378f9382980d7f5c534f731",
|
||||
"generatedAt": "2025-11-28T10:17:49.322460Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "git-worktrees",
|
||||
"description": "Manage Git worktrees for parallel Claude Code development. Use this skill when engineers ask to 'create a worktree', 'run parallel Claude sessions', 'work on multiple features simultaneously', or need help with worktree management."
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "cc574badc4b2894eded0641ebbbe10f833ddbdfd2fd14af65bb9e7a2136be820"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "f7a2362e27ed14488ad54b2b06df01584a37e740b83ad0350ac94228fa1e128f"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/SKILL.md",
|
||||
"sha256": "e88f756d68e9dfed00f104de48dfd67e28077efe1c9588e31be84226ed13d8e6"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/references/slash_command_template.md",
|
||||
"sha256": "1339335281efe5cdf362ca5cc7cb85041a273a3f0d3f114106db644089419e7d"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/references/worktree_commands.md",
|
||||
"sha256": "f54d9d373917749874392392fa58853097aad88f0668b4fbb950c6d1da3bea95"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/references/best_practices.md",
|
||||
"sha256": "bf7b5983a2dadb67d954c073c9a9f891b748a9e23630ba4626973e13ae8cdccd"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/scripts/list_worktrees.sh",
|
||||
"sha256": "09d910574a9578aff2b2079fbde46a2108462fb9411d5a67aa29eb4f7a9fbf09"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/scripts/sync_worktree.sh",
|
||||
"sha256": "5290d1508d1cb7491aa7e7e26f59c61e8f6b32cf6ea8c719c5ccf701fa7c50a0"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/scripts/create_worktree.sh",
|
||||
"sha256": "0f3ceb1a4f6476761c4cc529936f8d250f81c47ef5e05ad9a7c3db57008315c3"
|
||||
},
|
||||
{
|
||||
"path": "skills/git-worktrees/scripts/cleanup_worktrees.sh",
|
||||
"sha256": "fab4ee4e18eaf0ec109f6cad3379dba03312adc5fd744d93fa4502e5405e584b"
|
||||
}
|
||||
],
|
||||
"dirSha256": "b3894f41c934467d8114c180d756c70bbcb8cf4c8378f9382980d7f5c534f731"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
785
skills/git-worktrees/SKILL.md
Normal file
785
skills/git-worktrees/SKILL.md
Normal file
@@ -0,0 +1,785 @@
|
||||
---
|
||||
name: git-worktrees
|
||||
description: Manage Git worktrees for parallel Claude Code development. Use this skill when engineers ask to "create a worktree", "run parallel Claude sessions", "work on multiple features simultaneously", or need help with worktree management.
|
||||
---
|
||||
|
||||
# Git Worktrees for Claude Code
|
||||
|
||||
## Overview
|
||||
|
||||
Run multiple Claude Code sessions in parallel on different branches using Git worktrees. This skill provides simple scripts and workflows to set up, manage, and clean up worktrees, enabling true parallel development without conflicts.
|
||||
|
||||
**Why Worktrees?**
|
||||
- **Parallel Development**: Run multiple Claude Code instances simultaneously
|
||||
- **Zero Conflicts**: Each worktree has independent file state
|
||||
- **Fast Context Switching**: No need to stash/commit when switching tasks
|
||||
- **Isolated Experiments**: Try different approaches without affecting main work
|
||||
- **Long-Running Tasks**: Let Claude work in background while you continue in main
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Create a New Worktree (Super Easy!)
|
||||
|
||||
Just run the interactive script:
|
||||
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
```
|
||||
|
||||
This will:
|
||||
- ✅ Prompt for feature name
|
||||
- ✅ Create a new branch
|
||||
- ✅ Set up the worktree
|
||||
- ✅ Open in VS Code / editor
|
||||
- ✅ Give you the Claude Code setup command
|
||||
|
||||
**That's it!** The script handles all complexity.
|
||||
|
||||
---
|
||||
|
||||
### 2. View All Worktrees
|
||||
|
||||
```bash
|
||||
scripts/list_worktrees.sh
|
||||
```
|
||||
|
||||
Shows a clean, formatted list of all your worktrees with their branches and status.
|
||||
|
||||
---
|
||||
|
||||
### 3. Clean Up Old Worktrees
|
||||
|
||||
```bash
|
||||
scripts/cleanup_worktrees.sh
|
||||
```
|
||||
|
||||
Interactive removal of merged or abandoned worktrees.
|
||||
|
||||
---
|
||||
|
||||
## Core Workflow
|
||||
|
||||
### Pattern 1: Parallel Feature Development
|
||||
|
||||
**Scenario:** You want Claude to build feature A while you work on feature B.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Create worktree for feature A:**
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
# Enter: feature-a
|
||||
# Script creates: ../repo-feature-a/
|
||||
```
|
||||
|
||||
2. **Open Claude Code in the new worktree:**
|
||||
- The script outputs the path
|
||||
- Open Claude Code and navigate to that directory
|
||||
- Run `/init` to orient Claude
|
||||
|
||||
3. **Give Claude the task:**
|
||||
```
|
||||
"Build the user authentication feature with OAuth support"
|
||||
```
|
||||
|
||||
4. **Continue your work in main:**
|
||||
- Your original directory is unchanged
|
||||
- No conflicts, no waiting
|
||||
- Claude works in parallel
|
||||
|
||||
5. **When both are done, merge:**
|
||||
```bash
|
||||
# Review Claude's work
|
||||
cd ../repo-feature-a
|
||||
git log
|
||||
|
||||
# If good, merge back
|
||||
git checkout main
|
||||
git merge feature-a
|
||||
|
||||
# Clean up
|
||||
scripts/cleanup_worktrees.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Pattern 2: Long-Running Refactor
|
||||
|
||||
**Scenario:** You want Claude to refactor a large module while you continue development.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Create refactor worktree:**
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
# Enter: refactor-auth-module
|
||||
```
|
||||
|
||||
2. **Start Claude in refactor worktree:**
|
||||
```
|
||||
"Refactor the authentication module to use dependency injection"
|
||||
```
|
||||
|
||||
3. **Continue your daily work in main:**
|
||||
- No interruption
|
||||
- No merge conflicts
|
||||
- Check progress periodically
|
||||
|
||||
4. **Review and integrate when ready:**
|
||||
```bash
|
||||
cd ../repo-refactor-auth-module
|
||||
git log --oneline
|
||||
# Review changes
|
||||
|
||||
# Merge when satisfied
|
||||
git checkout main
|
||||
git merge refactor-auth-module
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Pattern 3: Multiple AI Agents (Advanced)
|
||||
|
||||
**Scenario:** You want 3 Claude instances working on different features simultaneously.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Create 3 worktrees:**
|
||||
```bash
|
||||
scripts/create_worktree.sh # feature-api-endpoints
|
||||
scripts/create_worktree.sh # feature-ui-dashboard
|
||||
scripts/create_worktree.sh # feature-email-notifications
|
||||
```
|
||||
|
||||
2. **Open 3 Claude Code sessions:**
|
||||
- Session 1: `../repo-feature-api-endpoints/`
|
||||
- Session 2: `../repo-feature-ui-dashboard/`
|
||||
- Session 3: `../repo-feature-email-notifications/`
|
||||
|
||||
3. **Assign tasks to each Claude:**
|
||||
- Claude 1: "Build REST API endpoints for user management"
|
||||
- Claude 2: "Create admin dashboard UI"
|
||||
- Claude 3: "Implement email notification system"
|
||||
|
||||
4. **Monitor progress:**
|
||||
```bash
|
||||
scripts/list_worktrees.sh
|
||||
```
|
||||
|
||||
5. **Merge features as they complete:**
|
||||
```bash
|
||||
# Feature by feature
|
||||
git checkout main
|
||||
git merge feature-api-endpoints
|
||||
git merge feature-ui-dashboard
|
||||
git merge feature-email-notifications
|
||||
|
||||
# Clean up
|
||||
scripts/cleanup_worktrees.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Pattern 4: Hotfix While Development Continues
|
||||
|
||||
**Scenario:** Production bug needs immediate fix while Claude is working on a feature.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Claude is already working in a feature worktree**
|
||||
- Let it continue, don't interrupt
|
||||
|
||||
2. **Create hotfix worktree from main:**
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
# Enter: hotfix-login-bug
|
||||
# Choose base branch: main
|
||||
```
|
||||
|
||||
3. **Fix the bug yourself or with another Claude session:**
|
||||
```bash
|
||||
cd ../repo-hotfix-login-bug
|
||||
# Make fixes
|
||||
git add .
|
||||
git commit -m "Fix login redirect bug"
|
||||
```
|
||||
|
||||
4. **Merge hotfix to main:**
|
||||
```bash
|
||||
git checkout main
|
||||
git merge hotfix-login-bug
|
||||
git push origin main
|
||||
```
|
||||
|
||||
5. **Sync feature worktree with latest main:**
|
||||
```bash
|
||||
cd ../repo-feature-xyz
|
||||
scripts/sync_worktree.sh
|
||||
# Merges latest main into feature branch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Essential Scripts
|
||||
|
||||
### scripts/create_worktree.sh
|
||||
|
||||
**Interactive worktree creation with all the right defaults.**
|
||||
|
||||
**What it does:**
|
||||
1. Prompts for feature name
|
||||
2. Validates git repo
|
||||
3. Creates branch from main (or specified base)
|
||||
4. Sets up worktree in parallel directory
|
||||
5. Outputs setup instructions
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
|
||||
# Prompts:
|
||||
# Feature name: my-feature
|
||||
# Base branch (default: main):
|
||||
#
|
||||
# Creates: ../repo-my-feature/
|
||||
# Branch: my-feature
|
||||
```
|
||||
|
||||
**Advanced usage:**
|
||||
```bash
|
||||
# Create from specific branch
|
||||
scripts/create_worktree.sh --base develop
|
||||
|
||||
# Specify location
|
||||
scripts/create_worktree.sh --dir ~/worktrees/my-feature
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### scripts/list_worktrees.sh
|
||||
|
||||
**Shows all active worktrees with status.**
|
||||
|
||||
**Output:**
|
||||
```
|
||||
╔════════════════════════════════════════════════╗
|
||||
║ Active Git Worktrees ║
|
||||
╚════════════════════════════════════════════════╝
|
||||
|
||||
📁 Main Worktree
|
||||
Path: /home/user/project
|
||||
Branch: main
|
||||
Status: clean
|
||||
|
||||
📁 Feature Worktrees
|
||||
Path: /home/user/project-feature-api
|
||||
Branch: feature-api
|
||||
Status: 2 uncommitted changes
|
||||
|
||||
Path: /home/user/project-refactor
|
||||
Branch: refactor-auth
|
||||
Status: clean
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### scripts/cleanup_worktrees.sh
|
||||
|
||||
**Interactive cleanup of old worktrees.**
|
||||
|
||||
**Features:**
|
||||
- Lists all worktrees with merge status
|
||||
- Identifies merged branches (safe to remove)
|
||||
- Prompts for confirmation
|
||||
- Safely removes worktree and branch
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
scripts/cleanup_worktrees.sh
|
||||
|
||||
# Output:
|
||||
# Found 3 worktrees
|
||||
#
|
||||
# 1. feature-api (merged to main) - Safe to remove
|
||||
# 2. feature-dashboard (not merged) - Keep
|
||||
# 3. old-experiment (not merged, 30 days old) - Consider removing
|
||||
#
|
||||
# Which worktrees to remove? (1,3): 1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### scripts/sync_worktree.sh
|
||||
|
||||
**Keep worktree up-to-date with main branch.**
|
||||
|
||||
**What it does:**
|
||||
1. Fetches latest from remote
|
||||
2. Merges main into current worktree branch
|
||||
3. Handles conflicts with guidance
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# From within a worktree
|
||||
cd ../repo-feature-api
|
||||
scripts/sync_worktree.sh
|
||||
|
||||
# Or specify worktree
|
||||
scripts/sync_worktree.sh ../repo-feature-api
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Claude Code Integration
|
||||
|
||||
### Important: Run /init in Each Worktree
|
||||
|
||||
When you open a new Claude Code session in a worktree, **always run `/init` first**:
|
||||
|
||||
```
|
||||
/init
|
||||
```
|
||||
|
||||
This ensures Claude:
|
||||
- Understands the codebase structure
|
||||
- Has proper context
|
||||
- Can navigate files correctly
|
||||
|
||||
### Recommended Claude Code Workflow
|
||||
|
||||
1. **Create worktree** (using script)
|
||||
2. **Open Claude Code** in worktree directory
|
||||
3. **Run `/init`** to orient Claude
|
||||
4. **Give task** to Claude
|
||||
5. **Monitor** via `git log` or file watching
|
||||
6. **Review** when complete
|
||||
7. **Merge** if satisfied
|
||||
8. **Cleanup** worktree
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
**Good names:**
|
||||
- `feature-user-auth` ✅
|
||||
- `refactor-api-layer` ✅
|
||||
- `hotfix-login-bug` ✅
|
||||
- `experiment-new-db` ✅
|
||||
|
||||
**Bad names:**
|
||||
- `test` ❌ (too vague)
|
||||
- `wt1` ❌ (meaningless)
|
||||
- `fixes` ❌ (unclear)
|
||||
|
||||
**Recommended format:**
|
||||
```
|
||||
<type>-<short-description>
|
||||
|
||||
Types:
|
||||
- feature-*
|
||||
- refactor-*
|
||||
- hotfix-*
|
||||
- experiment-*
|
||||
- review-*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Directory Structure
|
||||
|
||||
**Recommended layout:**
|
||||
```
|
||||
~/projects/
|
||||
└── myapp/ # Main worktree (main branch)
|
||||
├── myapp-feature-api/ # Feature worktree
|
||||
├── myapp-refactor-auth/ # Refactor worktree
|
||||
└── myapp-hotfix-bug/ # Hotfix worktree
|
||||
```
|
||||
|
||||
The scripts default to creating worktrees as siblings to your main directory with a naming pattern: `<repo>-<branch-name>`.
|
||||
|
||||
---
|
||||
|
||||
### When to Use Worktrees
|
||||
|
||||
**✅ Use worktrees when:**
|
||||
- Running multiple Claude Code sessions in parallel
|
||||
- Working on independent features simultaneously
|
||||
- Doing long-running refactors
|
||||
- Experimenting with major changes
|
||||
- Quick hotfixes during feature development
|
||||
- Code reviews without interrupting work
|
||||
|
||||
**❌ Don't use worktrees for:**
|
||||
- Simple branch switching (just use `git checkout`)
|
||||
- Minor tweaks (stash instead)
|
||||
- Single-task workflows
|
||||
- Very short-lived branches (< 1 hour)
|
||||
|
||||
---
|
||||
|
||||
### Keeping Worktrees in Sync
|
||||
|
||||
**Problem:** Feature branches can get out of date with main.
|
||||
|
||||
**Solution:** Regularly sync worktrees:
|
||||
|
||||
```bash
|
||||
# Option 1: Use the sync script
|
||||
cd ../repo-feature-api
|
||||
scripts/sync_worktree.sh
|
||||
|
||||
# Option 2: Manual sync
|
||||
cd ../repo-feature-api
|
||||
git fetch origin
|
||||
git merge origin/main
|
||||
```
|
||||
|
||||
**Recommended frequency:**
|
||||
- Daily for long-running features
|
||||
- After major merges to main
|
||||
- Before creating PRs
|
||||
|
||||
---
|
||||
|
||||
### Managing Many Worktrees
|
||||
|
||||
**Quick status of all worktrees:**
|
||||
```bash
|
||||
scripts/list_worktrees.sh
|
||||
```
|
||||
|
||||
**Regular cleanup (weekly):**
|
||||
```bash
|
||||
scripts/cleanup_worktrees.sh
|
||||
```
|
||||
|
||||
**Find stale worktrees:**
|
||||
```bash
|
||||
# Worktrees with old commits
|
||||
git worktree list | while read path branch commit; do
|
||||
cd "$path"
|
||||
last_commit=$(git log -1 --format=%cr)
|
||||
echo "$branch: Last commit $last_commit"
|
||||
done
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: "fatal: invalid reference"
|
||||
|
||||
**Cause:** Branch name has invalid characters
|
||||
|
||||
**Solution:** Use alphanumeric + hyphens only:
|
||||
```bash
|
||||
# Bad
|
||||
feature/my_feature ❌
|
||||
|
||||
# Good
|
||||
feature-my-feature ✅
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: "cannot remove worktree, path is not a working tree"
|
||||
|
||||
**Cause:** Worktree directory was manually deleted
|
||||
|
||||
**Solution:** Prune worktree references:
|
||||
```bash
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: Claude seems "lost" in worktree
|
||||
|
||||
**Cause:** Didn't run `/init` after opening worktree
|
||||
|
||||
**Solution:** Always run `/init` when starting Claude in a new worktree:
|
||||
```
|
||||
/init
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: Merge conflicts when syncing worktree
|
||||
|
||||
**Cause:** Changes in worktree conflict with main
|
||||
|
||||
**Solution 1:** Resolve conflicts manually:
|
||||
```bash
|
||||
cd ../repo-feature-api
|
||||
git fetch origin
|
||||
git merge origin/main
|
||||
# Fix conflicts in editor
|
||||
git add .
|
||||
git commit -m "Merge main and resolve conflicts"
|
||||
```
|
||||
|
||||
**Solution 2:** If you want to discard worktree changes and restart:
|
||||
```bash
|
||||
cd ../repo-feature-api
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
# Start feature over
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: "Cannot lock ref" error
|
||||
|
||||
**Cause:** Branch exists in multiple worktrees
|
||||
|
||||
**Solution:** You can't have the same branch checked out in multiple worktrees. Create a new branch:
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
# Use a different branch name
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: Worktree takes up too much disk space
|
||||
|
||||
**Cause:** Git worktrees share the `.git` directory, but files are duplicated
|
||||
|
||||
**Solution 1:** Clean up old worktrees:
|
||||
```bash
|
||||
scripts/cleanup_worktrees.sh
|
||||
```
|
||||
|
||||
**Solution 2:** For large repos, use sparse-checkout:
|
||||
```bash
|
||||
git -C ../repo-feature-api sparse-checkout set src/ tests/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Slash Command
|
||||
|
||||
Create a `/worktree` command for Claude Code. See `references/slash_command_template.md` for the complete setup.
|
||||
|
||||
**Usage after setup:**
|
||||
```
|
||||
/worktree feature-new-api
|
||||
```
|
||||
|
||||
Claude will:
|
||||
1. Create the worktree
|
||||
2. Provide setup instructions
|
||||
3. Offer to continue the conversation in the new worktree
|
||||
|
||||
---
|
||||
|
||||
### Sharing Worktrees in Team
|
||||
|
||||
**Worktrees are local only**, but you can share the workflow:
|
||||
|
||||
1. **Share branch, not worktree:**
|
||||
```bash
|
||||
cd ../repo-feature-api
|
||||
git push origin feature-api
|
||||
|
||||
# Teammate creates their own worktree
|
||||
git worktree add ../repo-feature-api feature-api
|
||||
```
|
||||
|
||||
2. **Document your worktree structure** in team docs
|
||||
|
||||
3. **Use consistent naming** across team
|
||||
|
||||
---
|
||||
|
||||
### Worktree Performance Optimization
|
||||
|
||||
**For large repos:**
|
||||
|
||||
1. **Use sparse-checkout** (only checkout files you need):
|
||||
```bash
|
||||
git -C ../repo-feature-api sparse-checkout init
|
||||
git -C ../repo-feature-api sparse-checkout set src/ tests/
|
||||
```
|
||||
|
||||
2. **Use worktree prune regularly:**
|
||||
```bash
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
3. **Limit concurrent worktrees** to 3-5 for best performance
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows Summary
|
||||
|
||||
### Quick Reference
|
||||
|
||||
| Task | Command |
|
||||
|------|---------|
|
||||
| Create new worktree | `scripts/create_worktree.sh` |
|
||||
| List all worktrees | `scripts/list_worktrees.sh` |
|
||||
| Clean up worktrees | `scripts/cleanup_worktrees.sh` |
|
||||
| Sync with main | `scripts/sync_worktree.sh` |
|
||||
| Manual create | `git worktree add ../path branch-name` |
|
||||
| Manual list | `git worktree list` |
|
||||
| Manual remove | `git worktree remove ../path` |
|
||||
| Prune references | `git worktree prune` |
|
||||
|
||||
---
|
||||
|
||||
## Real-World Examples
|
||||
|
||||
### Example 1: Parallel API & UI Development
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Create API worktree
|
||||
scripts/create_worktree.sh
|
||||
# Name: feature-api
|
||||
|
||||
# Create UI worktree
|
||||
scripts/create_worktree.sh
|
||||
# Name: feature-ui
|
||||
```
|
||||
|
||||
**Execution:**
|
||||
- Claude 1 in `../repo-feature-api`: "Build REST API for user management"
|
||||
- Claude 2 in `../repo-feature-ui`: "Create React UI for user management"
|
||||
- You in main: Continue other work
|
||||
|
||||
**Merge:**
|
||||
```bash
|
||||
git checkout main
|
||||
git merge feature-api
|
||||
git merge feature-ui
|
||||
scripts/cleanup_worktrees.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Example 2: Code Review Without Context Switching
|
||||
|
||||
**Scenario:** Need to review PR while Claude works on feature
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Claude is working in feature worktree
|
||||
# You need to review PR #123
|
||||
|
||||
scripts/create_worktree.sh
|
||||
# Name: review-pr-123
|
||||
# Base: pr-branch-name
|
||||
```
|
||||
|
||||
**Execution:**
|
||||
- Review code in `../repo-review-pr-123`
|
||||
- Claude continues work in `../repo-feature-xyz`
|
||||
- No context switching needed
|
||||
|
||||
**Cleanup:**
|
||||
```bash
|
||||
# After review
|
||||
scripts/cleanup_worktrees.sh
|
||||
# Select review-pr-123
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Example 3: Experimentation Without Risk
|
||||
|
||||
**Scenario:** Want to try a radical refactor without breaking current work
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
# Name: experiment-new-architecture
|
||||
```
|
||||
|
||||
**Execution:**
|
||||
- Experiment freely in `../repo-experiment-new-architecture`
|
||||
- Main worktree remains stable
|
||||
- If experiment fails, just delete worktree
|
||||
|
||||
**Decision:**
|
||||
```bash
|
||||
# If experiment succeeded
|
||||
git checkout main
|
||||
git merge experiment-new-architecture
|
||||
|
||||
# If experiment failed
|
||||
scripts/cleanup_worktrees.sh
|
||||
# Delete experiment worktree (no harm done)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tips for Maximum Productivity
|
||||
|
||||
### 1. **Name Worktrees Descriptively**
|
||||
- You'll thank yourself later when you have 5 worktrees open
|
||||
|
||||
### 2. **Always Run /init**
|
||||
- First thing when opening Claude in a new worktree
|
||||
|
||||
### 3. **Merge Frequently**
|
||||
- Don't let worktrees diverge for weeks
|
||||
- Sync with main regularly
|
||||
|
||||
### 4. **Clean Up Weekly**
|
||||
- Run `scripts/cleanup_worktrees.sh` every Friday
|
||||
- Keep your workspace tidy
|
||||
|
||||
### 5. **Use Scripts**
|
||||
- Don't memorize git worktree commands
|
||||
- Scripts handle edge cases and validation
|
||||
|
||||
### 6. **Monitor Progress**
|
||||
- Use `scripts/list_worktrees.sh` to see what's active
|
||||
- Check git logs in worktrees periodically
|
||||
|
||||
### 7. **Limit Concurrent Sessions**
|
||||
- 3-5 worktrees max for best performance
|
||||
- More than that gets hard to manage
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
### Scripts
|
||||
|
||||
- **create_worktree.sh** - Interactive worktree creation
|
||||
- **list_worktrees.sh** - Show all active worktrees
|
||||
- **cleanup_worktrees.sh** - Remove old worktrees
|
||||
- **sync_worktree.sh** - Keep worktrees synchronized
|
||||
|
||||
### References
|
||||
|
||||
- **worktree_commands.md** - Complete Git worktree command reference
|
||||
- **best_practices.md** - Detailed best practices and patterns
|
||||
- **slash_command_template.md** - Create custom `/worktree` command
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Git worktrees enable true parallel development with Claude Code:
|
||||
|
||||
✅ **Run multiple Claude sessions** without conflicts
|
||||
✅ **Switch contexts instantly** without stashing
|
||||
✅ **Experiment safely** without breaking main
|
||||
✅ **Simple scripts** handle all complexity
|
||||
✅ **Clean workflows** for common scenarios
|
||||
|
||||
**Get started:**
|
||||
```bash
|
||||
scripts/create_worktree.sh
|
||||
```
|
||||
|
||||
**That's it!** The scripts make worktrees simple and practical.
|
||||
625
skills/git-worktrees/references/best_practices.md
Normal file
625
skills/git-worktrees/references/best_practices.md
Normal file
@@ -0,0 +1,625 @@
|
||||
# Git Worktrees Best Practices
|
||||
|
||||
Proven patterns and recommendations for using worktrees effectively with Claude Code.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Naming Conventions](#naming-conventions)
|
||||
2. [Directory Organization](#directory-organization)
|
||||
3. [When to Use Worktrees](#when-to-use-worktrees)
|
||||
4. [Lifecycle Management](#lifecycle-management)
|
||||
5. [Performance Optimization](#performance-optimization)
|
||||
6. [Team Collaboration](#team-collaboration)
|
||||
7. [Claude Code Integration](#claude-code-integration)
|
||||
|
||||
---
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
### Branch Names
|
||||
|
||||
**Use descriptive, hierarchical names:**
|
||||
|
||||
```
|
||||
<type>-<short-description>
|
||||
|
||||
Types:
|
||||
- feature-* New features
|
||||
- refactor-* Code refactoring
|
||||
- hotfix-* Urgent bug fixes
|
||||
- experiment-* Experimental changes
|
||||
- review-* Code reviews
|
||||
- test-* Testing branches
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
✅ Good:
|
||||
- feature-user-authentication
|
||||
- refactor-api-layer
|
||||
- hotfix-login-redirect
|
||||
- experiment-new-db-schema
|
||||
- review-pr-123
|
||||
|
||||
❌ Bad:
|
||||
- test
|
||||
- wt1
|
||||
- fixes
|
||||
- my-branch
|
||||
- abc
|
||||
```
|
||||
|
||||
**Why it matters:**
|
||||
- Easy to identify purpose months later
|
||||
- Clear for team members
|
||||
- Searchable and filterable
|
||||
- Self-documenting
|
||||
|
||||
---
|
||||
|
||||
### Directory Names
|
||||
|
||||
**Match branch names with prefix:**
|
||||
|
||||
```bash
|
||||
# Pattern: <repo-name>-<branch-name>
|
||||
|
||||
Example repository: myapp
|
||||
|
||||
Worktrees:
|
||||
- myapp-feature-api
|
||||
- myapp-refactor-auth
|
||||
- myapp-hotfix-login
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Immediately recognize which repo
|
||||
- See all worktrees with `ls ../`
|
||||
- Avoid confusion with multiple projects
|
||||
|
||||
**Alternative patterns:**
|
||||
```bash
|
||||
# By date (for temporary worktrees)
|
||||
myapp-2025-01-15-hotfix
|
||||
|
||||
# By ticket number
|
||||
myapp-JIRA-1234
|
||||
|
||||
# By developer (in shared environments)
|
||||
myapp-john-feature-api
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Directory Organization
|
||||
|
||||
### Recommended Structure
|
||||
|
||||
```
|
||||
~/projects/
|
||||
└── myapp/ # Main worktree (main branch)
|
||||
├── myapp-feature-api/ # Feature worktree
|
||||
├── myapp-feature-ui/ # Feature worktree
|
||||
├── myapp-refactor-auth/ # Refactor worktree
|
||||
└── myapp-hotfix-login/ # Hotfix worktree
|
||||
```
|
||||
|
||||
**Advantages:**
|
||||
- All related worktrees grouped together
|
||||
- Easy to find with `ls ../`
|
||||
- Clean navigation between worktrees
|
||||
|
||||
---
|
||||
|
||||
### Alternative: Dedicated Worktrees Directory
|
||||
|
||||
```
|
||||
~/projects/
|
||||
├── myapp/ # Main worktree
|
||||
└── worktrees/
|
||||
├── myapp-feature-api/
|
||||
├── myapp-feature-ui/
|
||||
└── myapp-refactor-auth/
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
- Working with many worktrees
|
||||
- Want clear separation
|
||||
- Sharing machine with others
|
||||
|
||||
---
|
||||
|
||||
### What NOT to Do
|
||||
|
||||
```
|
||||
❌ Nested worktrees:
|
||||
~/projects/
|
||||
└── myapp/
|
||||
└── feature-api/ # Don't nest inside repo
|
||||
|
||||
❌ Unrelated locations:
|
||||
~/projects/myapp/ # Main
|
||||
~/Documents/api-feature/ # Confusing!
|
||||
/tmp/worktree-123/ # Gets deleted
|
||||
|
||||
❌ Generic names:
|
||||
~/projects/myapp/
|
||||
├── wt1/
|
||||
├── temp/
|
||||
└── test/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## When to Use Worktrees
|
||||
|
||||
### ✅ Use Worktrees For:
|
||||
|
||||
**1. Parallel AI Development**
|
||||
- Multiple Claude Code sessions on different features
|
||||
- Long-running Claude tasks while you continue work
|
||||
- Experimenting with different AI approaches
|
||||
|
||||
**2. Context Switching**
|
||||
- Hotfix needed while working on feature
|
||||
- Code review without interrupting current work
|
||||
- Testing changes in isolation
|
||||
|
||||
**3. Comparison & Testing**
|
||||
- Compare two implementations side-by-side
|
||||
- Test different approaches
|
||||
- A/B testing code changes
|
||||
|
||||
**4. Long-Running Tasks**
|
||||
- Major refactors
|
||||
- Database migrations
|
||||
- Performance optimization
|
||||
|
||||
---
|
||||
|
||||
### ❌ DON'T Use Worktrees For:
|
||||
|
||||
**1. Quick Branch Switches**
|
||||
```bash
|
||||
# Just use checkout for quick switches
|
||||
git checkout other-branch
|
||||
# Not: git worktree add ../temp other-branch
|
||||
```
|
||||
|
||||
**2. Very Short-Lived Work** (< 1 hour)
|
||||
```bash
|
||||
# Use stash instead
|
||||
git stash push -m "Quick fix"
|
||||
git checkout main
|
||||
# ... do fix ...
|
||||
git checkout original-branch
|
||||
git stash pop
|
||||
```
|
||||
|
||||
**3. Simple Merges**
|
||||
```bash
|
||||
# Direct merge is simpler
|
||||
git merge feature-branch
|
||||
# Not: git worktree add ../temp feature-branch
|
||||
```
|
||||
|
||||
**4. Single-Tasking Workflow**
|
||||
- If you work on one thing at a time, branches are fine
|
||||
- Worktrees add overhead without benefit
|
||||
|
||||
---
|
||||
|
||||
## Lifecycle Management
|
||||
|
||||
### Creation Checklist
|
||||
|
||||
**Before creating:**
|
||||
- [ ] Is the branch name descriptive?
|
||||
- [ ] Is this task long enough to warrant a worktree?
|
||||
- [ ] Will I need to switch contexts during this work?
|
||||
- [ ] Do I have disk space? (worktrees duplicate files)
|
||||
|
||||
**During creation:**
|
||||
- [ ] Use the create script: `scripts/create_worktree.sh`
|
||||
- [ ] Note the path for later
|
||||
- [ ] Add to tracking system if managing many
|
||||
|
||||
---
|
||||
|
||||
### Active Maintenance
|
||||
|
||||
**Daily:**
|
||||
- Check status: `scripts/list_worktrees.sh`
|
||||
- Commit progress in each worktree
|
||||
- Sync with main if needed: `scripts/sync_worktree.sh`
|
||||
|
||||
**Weekly:**
|
||||
- Clean up merged worktrees: `scripts/cleanup_worktrees.sh`
|
||||
- Review active worktrees
|
||||
- Archive or delete abandoned experiments
|
||||
|
||||
**Monthly:**
|
||||
- Audit all worktrees
|
||||
- Remove stale worktrees
|
||||
- Update documentation/notes
|
||||
|
||||
---
|
||||
|
||||
### Cleanup Workflow
|
||||
|
||||
**When to clean up:**
|
||||
- ✅ Branch merged to main
|
||||
- ✅ Task completed
|
||||
- ✅ Experiment concluded
|
||||
- ✅ Review finished
|
||||
- ⚠️ Abandoned (but check for uncommitted work!)
|
||||
|
||||
**How to clean up safely:**
|
||||
```bash
|
||||
# 1. Check status
|
||||
cd ../myapp-feature-api
|
||||
git status
|
||||
|
||||
# 2. Check if merged
|
||||
cd <main-repo>
|
||||
git branch --merged main | grep feature-api
|
||||
|
||||
# 3. If merged, safe to remove
|
||||
scripts/cleanup_worktrees.sh
|
||||
# Select the worktree
|
||||
|
||||
# 4. Verify removal
|
||||
scripts/list_worktrees.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Disk Space Management
|
||||
|
||||
**Monitor usage:**
|
||||
```bash
|
||||
# Check worktree sizes
|
||||
du -sh ../myapp-*
|
||||
|
||||
# Check total usage
|
||||
du -sh ../
|
||||
```
|
||||
|
||||
**Optimization strategies:**
|
||||
|
||||
**1. Use Sparse Checkout** (for large repos):
|
||||
```bash
|
||||
cd worktree
|
||||
git sparse-checkout init
|
||||
git sparse-checkout set src/ tests/
|
||||
```
|
||||
|
||||
**2. Clean Build Artifacts:**
|
||||
```bash
|
||||
# Add to .gitignore
|
||||
node_modules/
|
||||
target/
|
||||
build/
|
||||
*.pyc
|
||||
```
|
||||
|
||||
**3. Limit Concurrent Worktrees:**
|
||||
- Keep 3-5 active worktrees maximum
|
||||
- Clean up old ones regularly
|
||||
|
||||
---
|
||||
|
||||
### Git Performance
|
||||
|
||||
**Shared objects are efficient:**
|
||||
- Git history is shared (not duplicated)
|
||||
- Only working files are duplicated
|
||||
- Refs and config are shared
|
||||
|
||||
**Keep worktrees healthy:**
|
||||
```bash
|
||||
# Prune stale references regularly
|
||||
git worktree prune
|
||||
|
||||
# Garbage collect periodically
|
||||
git gc --aggressive
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Team Collaboration
|
||||
|
||||
### Communication
|
||||
|
||||
**Document active worktrees:**
|
||||
```markdown
|
||||
# In your team wiki or README
|
||||
|
||||
## Active Worktrees
|
||||
|
||||
| Developer | Worktree | Branch | Purpose | Started |
|
||||
|-----------|----------|--------|---------|---------|
|
||||
| Alice | feature-api | feature-api | New API endpoints | 2025-01-10 |
|
||||
| Bob | refactor-db | refactor-db | Database refactor | 2025-01-08 |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Sharing Workflow (Not Worktrees!)
|
||||
|
||||
**What to share:**
|
||||
```bash
|
||||
# Push your branch
|
||||
cd ../myapp-feature-api
|
||||
git push origin feature-api
|
||||
|
||||
# Teammate creates their own worktree
|
||||
git worktree add ../myapp-feature-api feature-api
|
||||
```
|
||||
|
||||
**Don't try to:**
|
||||
- Share worktree directories (they're local)
|
||||
- Commit worktree paths to git
|
||||
- Sync worktree locations across machines
|
||||
|
||||
---
|
||||
|
||||
### Team Conventions
|
||||
|
||||
**Establish team standards:**
|
||||
|
||||
```yaml
|
||||
# .github/WORKTREE_GUIDE.md
|
||||
|
||||
Naming Convention:
|
||||
format: <type>-<description>
|
||||
types: feature, refactor, hotfix, experiment
|
||||
|
||||
Directory Structure:
|
||||
location: Sibling to main repo
|
||||
format: <repo-name>-<branch-name>
|
||||
|
||||
Cleanup Policy:
|
||||
frequency: Weekly
|
||||
criteria: Merged branches, abandoned > 30 days
|
||||
|
||||
Scripts:
|
||||
create: scripts/create_worktree.sh
|
||||
list: scripts/list_worktrees.sh
|
||||
cleanup: scripts/cleanup_worktrees.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Claude Code Integration
|
||||
|
||||
### Always Run /init
|
||||
|
||||
**Critical step when opening a new worktree in Claude Code:**
|
||||
|
||||
```
|
||||
1. Create worktree
|
||||
2. Open Claude Code in worktree directory
|
||||
3. Run: /init
|
||||
4. Give Claude the task
|
||||
```
|
||||
|
||||
**Why `/init` matters:**
|
||||
- Orients Claude to codebase structure
|
||||
- Establishes proper context
|
||||
- Enables correct file navigation
|
||||
- Prevents confusion about file locations
|
||||
|
||||
---
|
||||
|
||||
### Optimal Claude Code Workflow
|
||||
|
||||
**Pattern 1: Parallel Features**
|
||||
|
||||
```bash
|
||||
# Terminal 1: Create first feature worktree
|
||||
scripts/create_worktree.sh
|
||||
# Name: feature-api
|
||||
|
||||
# Terminal 2: Create second feature worktree
|
||||
scripts/create_worktree.sh
|
||||
# Name: feature-ui
|
||||
|
||||
# Claude Session 1: Open feature-api worktree
|
||||
cd ../myapp-feature-api
|
||||
code .
|
||||
# In Claude: /init
|
||||
# Task: "Build REST API for user management"
|
||||
|
||||
# Claude Session 2: Open feature-ui worktree
|
||||
cd ../myapp-feature-ui
|
||||
code .
|
||||
# In Claude: /init
|
||||
# Task: "Create React UI for user management"
|
||||
|
||||
# Monitor both
|
||||
scripts/list_worktrees.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Pattern 2: Review + Development**
|
||||
|
||||
```bash
|
||||
# Claude working on feature
|
||||
cd ../myapp-feature-xyz
|
||||
# Claude is actively coding
|
||||
|
||||
# You need to review a PR
|
||||
scripts/create_worktree.sh
|
||||
# Name: review-pr-123
|
||||
|
||||
# Open separate editor for review
|
||||
cd ../myapp-review-pr-123
|
||||
code .
|
||||
|
||||
# No context switching needed!
|
||||
# Claude continues in feature worktree
|
||||
# You review in review worktree
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Managing Multiple Claude Sessions
|
||||
|
||||
**Track active sessions:**
|
||||
```
|
||||
Feature API → ../myapp-feature-api → Port 3001
|
||||
Feature UI → ../myapp-feature-ui → Port 3002
|
||||
Refactor Auth → ../myapp-refactor-auth → Port 3003
|
||||
```
|
||||
|
||||
**Best practices:**
|
||||
- Limit to 3-5 concurrent Claude sessions
|
||||
- Use descriptive terminal/window titles
|
||||
- Keep a log of what each Claude is working on
|
||||
- Monitor progress regularly
|
||||
|
||||
---
|
||||
|
||||
### When Claude Gets "Lost"
|
||||
|
||||
**Symptoms:**
|
||||
- Can't find files
|
||||
- References wrong paths
|
||||
- Seems confused about structure
|
||||
|
||||
**Solution:**
|
||||
```
|
||||
1. Run: /init
|
||||
2. If that doesn't help, restart Claude session
|
||||
3. Verify you're in correct worktree: pwd
|
||||
4. Check git branch: git branch --show-current
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Pitfalls & Solutions
|
||||
|
||||
### Pitfall 1: Too Many Worktrees
|
||||
|
||||
**Problem:** Managing 10+ worktrees becomes overwhelming
|
||||
|
||||
**Solution:**
|
||||
- Limit to 3-5 active worktrees
|
||||
- Clean up weekly
|
||||
- Use projects/issues for tracking longer-term work
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 2: Forgetting to Sync
|
||||
|
||||
**Problem:** Worktree gets far behind main, causing conflicts
|
||||
|
||||
**Solution:**
|
||||
- Set reminder to sync daily
|
||||
- Use script: `scripts/sync_worktree.sh`
|
||||
- Keep feature branches short-lived
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 3: Abandoning Worktrees
|
||||
|
||||
**Problem:** Old worktrees with uncommitted work left behind
|
||||
|
||||
**Solution:**
|
||||
- Weekly cleanup ritual
|
||||
- Use `scripts/list_worktrees.sh` to audit
|
||||
- Document important worktrees
|
||||
- Set calendar reminder
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 4: Wrong Branch Checked Out
|
||||
|
||||
**Problem:** Same branch in multiple worktrees (git won't allow)
|
||||
|
||||
**Solution:**
|
||||
- Each worktree needs unique branch
|
||||
- Use branch naming to avoid confusion
|
||||
- Check before creating: `git branch`
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 5: Disk Space Issues
|
||||
|
||||
**Problem:** Running out of disk space with many worktrees
|
||||
|
||||
**Solution:**
|
||||
- Use sparse checkout
|
||||
- Clean build artifacts regularly
|
||||
- Limit concurrent worktrees
|
||||
- Monitor with `du -sh ../myapp-*`
|
||||
|
||||
---
|
||||
|
||||
## Checklists
|
||||
|
||||
### Before Creating Worktree
|
||||
|
||||
- [ ] Is the task substantial enough?
|
||||
- [ ] Do I have a clear branch name?
|
||||
- [ ] Do I have sufficient disk space?
|
||||
- [ ] Is this better than just using `git checkout`?
|
||||
|
||||
---
|
||||
|
||||
### After Creating Worktree
|
||||
|
||||
- [ ] Opened in editor/IDE
|
||||
- [ ] Ran `/init` in Claude Code
|
||||
- [ ] Noted purpose/task
|
||||
- [ ] Set up environment (npm install, etc.)
|
||||
|
||||
---
|
||||
|
||||
### Before Removing Worktree
|
||||
|
||||
- [ ] Checked for uncommitted changes
|
||||
- [ ] Verified branch is merged (or don't need it)
|
||||
- [ ] Pushed any important commits
|
||||
- [ ] Informed team if collaborative work
|
||||
|
||||
---
|
||||
|
||||
### Weekly Maintenance
|
||||
|
||||
- [ ] Run `scripts/list_worktrees.sh`
|
||||
- [ ] Run `scripts/cleanup_worktrees.sh`
|
||||
- [ ] Check disk usage
|
||||
- [ ] Update documentation
|
||||
|
||||
---
|
||||
|
||||
## Summary of Best Practices
|
||||
|
||||
**Do:**
|
||||
- ✅ Use descriptive branch/directory names
|
||||
- ✅ Create worktrees as siblings to main repo
|
||||
- ✅ Run `/init` when opening Claude in new worktree
|
||||
- ✅ Clean up regularly (weekly)
|
||||
- ✅ Limit to 3-5 concurrent worktrees
|
||||
- ✅ Sync with main frequently
|
||||
- ✅ Use provided scripts for common tasks
|
||||
|
||||
**Don't:**
|
||||
- ❌ Nest worktrees inside repository
|
||||
- ❌ Create worktrees for quick tasks
|
||||
- ❌ Forget to run `/init` in Claude
|
||||
- ❌ Let worktrees accumulate indefinitely
|
||||
- ❌ Use generic names (test, temp, wt1)
|
||||
- ❌ Share worktree directories across machines
|
||||
|
||||
---
|
||||
|
||||
**Key Principle:**
|
||||
> Worktrees are a power tool. Use them intentionally for parallel development, not as a replacement for basic branching.
|
||||
519
skills/git-worktrees/references/slash_command_template.md
Normal file
519
skills/git-worktrees/references/slash_command_template.md
Normal file
@@ -0,0 +1,519 @@
|
||||
# Custom /worktree Slash Command Template
|
||||
|
||||
Create a custom `/worktree` command for Claude Code to streamline worktree creation.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This template allows you to create a slash command that:
|
||||
1. Creates a new Git worktree
|
||||
2. Provides setup instructions
|
||||
3. Offers to continue the conversation in the new worktree
|
||||
|
||||
**Usage after setup:**
|
||||
```
|
||||
/worktree feature-new-api
|
||||
```
|
||||
|
||||
Claude will create the worktree and guide you through the next steps.
|
||||
|
||||
---
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
### Step 1: Create Command File
|
||||
|
||||
Create a new file in your Claude Code commands directory:
|
||||
|
||||
```bash
|
||||
# For project-specific command
|
||||
mkdir -p .claude/commands
|
||||
touch .claude/commands/worktree.md
|
||||
|
||||
# For global command (all projects)
|
||||
mkdir -p ~/.claude/commands
|
||||
touch ~/.claude/commands/worktree.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Add Command Content
|
||||
|
||||
Copy this template into `worktree.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Create a new Git worktree for parallel development with Claude Code
|
||||
---
|
||||
|
||||
# Create Git Worktree
|
||||
|
||||
{{#if (not args.0)}}
|
||||
**Usage:** `/worktree <branch-name> [base-branch]`
|
||||
|
||||
**Examples:**
|
||||
- `/worktree feature-api` - Create worktree from main
|
||||
- `/worktree feature-ui develop` - Create worktree from develop
|
||||
- `/worktree hotfix-urgent` - Create hotfix worktree
|
||||
|
||||
**What this does:**
|
||||
1. Creates a new Git worktree
|
||||
2. Sets up the directory structure
|
||||
3. Provides setup instructions
|
||||
|
||||
{{else}}
|
||||
|
||||
## Creating Worktree: {{args.0}}
|
||||
|
||||
Let me create a new Git worktree for parallel development.
|
||||
|
||||
**Branch name:** `{{args.0}}`
|
||||
{{#if args.1}}
|
||||
**Base branch:** `{{args.1}}`
|
||||
{{else}}
|
||||
**Base branch:** `main` (default)
|
||||
{{/if}}
|
||||
|
||||
### Step 1: Create the Worktree
|
||||
|
||||
Run this command in your terminal:
|
||||
|
||||
\`\`\`bash
|
||||
scripts/create_worktree.sh
|
||||
\`\`\`
|
||||
|
||||
When prompted:
|
||||
- Feature name: **{{args.0}}**
|
||||
{{#if args.1}}
|
||||
- Base branch: **{{args.1}}**
|
||||
{{else}}
|
||||
- Base branch: **main** (or press Enter for default)
|
||||
{{/if}}
|
||||
|
||||
The script will create the worktree in a sibling directory.
|
||||
|
||||
### Step 2: Open in New Claude Code Session
|
||||
|
||||
After the script completes:
|
||||
|
||||
1. Note the worktree path (shown by the script)
|
||||
2. Open a new Claude Code window
|
||||
3. Navigate to the worktree directory
|
||||
4. **Important:** Run `/init` to orient Claude
|
||||
|
||||
### Step 3: Start Development
|
||||
|
||||
Once in the new worktree with Claude initialized, I can help you:
|
||||
- Implement the feature
|
||||
- Write tests
|
||||
- Create documentation
|
||||
- Review code
|
||||
|
||||
### Alternative: Manual Creation
|
||||
|
||||
If you prefer manual setup:
|
||||
|
||||
\`\`\`bash
|
||||
# Get repository root
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
REPO_NAME=$(basename "$REPO_ROOT")
|
||||
|
||||
# Create worktree
|
||||
{{#if args.1}}
|
||||
git worktree add ../$REPO_NAME-{{args.0}} -b {{args.0}} {{args.1}}
|
||||
{{else}}
|
||||
git worktree add ../$REPO_NAME-{{args.0}} -b {{args.0}} main
|
||||
{{/if}}
|
||||
|
||||
# Open in editor
|
||||
cd ../$REPO_NAME-{{args.0}}
|
||||
code .
|
||||
\`\`\`
|
||||
|
||||
### Managing Worktrees
|
||||
|
||||
**List all worktrees:**
|
||||
\`\`\`bash
|
||||
scripts/list_worktrees.sh
|
||||
\`\`\`
|
||||
|
||||
**Sync with main:**
|
||||
\`\`\`bash
|
||||
scripts/sync_worktree.sh
|
||||
\`\`\`
|
||||
|
||||
**Clean up when done:**
|
||||
\`\`\`bash
|
||||
scripts/cleanup_worktrees.sh
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
**Would you like me to help with anything else before you switch to the new worktree?**
|
||||
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Test the Command
|
||||
|
||||
```bash
|
||||
# In Claude Code, type:
|
||||
/worktree feature-new-api
|
||||
|
||||
# Or with custom base branch:
|
||||
/worktree feature-ui develop
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Advanced Template (With Automatic Creation)
|
||||
|
||||
For users who want Claude to automatically create the worktree (not just show instructions):
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Create and set up a new Git worktree for parallel development
|
||||
---
|
||||
|
||||
# Create Git Worktree: {{args.0}}
|
||||
|
||||
{{#if (not args.0)}}
|
||||
**Error:** Branch name required
|
||||
|
||||
**Usage:** `/worktree <branch-name> [base-branch]`
|
||||
|
||||
**Examples:**
|
||||
- `/worktree feature-api`
|
||||
- `/worktree feature-ui develop`
|
||||
{{else}}
|
||||
|
||||
I'll create a new Git worktree for `{{args.0}}`.
|
||||
|
||||
## Creating Worktree
|
||||
|
||||
\`\`\`bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuration
|
||||
BRANCH_NAME="{{args.0}}"
|
||||
{{#if args.1}}
|
||||
BASE_BRANCH="{{args.1}}"
|
||||
{{else}}
|
||||
BASE_BRANCH="main"
|
||||
{{/if}}
|
||||
|
||||
# Get repository info
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
REPO_NAME=$(basename "$REPO_ROOT")
|
||||
WORKTREE_DIR="$(dirname "$REPO_ROOT")/${REPO_NAME}-${BRANCH_NAME}"
|
||||
|
||||
# Validate
|
||||
if [ ! -d "$REPO_ROOT/.git" ]; then
|
||||
echo "Error: Not in a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if branch exists
|
||||
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
|
||||
echo "⚠ Branch $BRANCH_NAME already exists"
|
||||
echo "Using existing branch..."
|
||||
git worktree add "$WORKTREE_DIR" "$BRANCH_NAME"
|
||||
else
|
||||
echo "✓ Creating new branch from $BASE_BRANCH..."
|
||||
git worktree add -b "$BRANCH_NAME" "$WORKTREE_DIR" "$BASE_BRANCH"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✓ Worktree created successfully!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Open new Claude Code window"
|
||||
echo "2. Navigate to: $WORKTREE_DIR"
|
||||
echo "3. Run: /init"
|
||||
echo "4. Start development!"
|
||||
\`\`\`
|
||||
|
||||
Run the script above to create the worktree.
|
||||
|
||||
## What's Next?
|
||||
|
||||
After creating the worktree:
|
||||
|
||||
1. **Open in new window:** \`code {{WORKTREE_PATH}}\`
|
||||
2. **Run /init:** To orient Claude in the new environment
|
||||
3. **Start coding:** I'll be ready to help with {{args.0}}!
|
||||
|
||||
## Useful Commands
|
||||
|
||||
**View all worktrees:**
|
||||
\`\`\`bash
|
||||
git worktree list
|
||||
\`\`\`
|
||||
|
||||
**When done, merge back:**
|
||||
\`\`\`bash
|
||||
git checkout main
|
||||
git merge {{args.0}}
|
||||
\`\`\`
|
||||
|
||||
**Remove worktree:**
|
||||
\`\`\`bash
|
||||
git worktree remove ../{{REPO_NAME}}-{{args.0}}
|
||||
git branch -d {{args.0}}
|
||||
\`\`\`
|
||||
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: Simple Feature
|
||||
|
||||
```
|
||||
User: /worktree feature-authentication
|
||||
```
|
||||
|
||||
**Claude's response:**
|
||||
- Shows worktree creation instructions
|
||||
- Explains next steps
|
||||
- Offers to continue in new worktree
|
||||
|
||||
---
|
||||
|
||||
### Example 2: Custom Base Branch
|
||||
|
||||
```
|
||||
User: /worktree feature-dashboard develop
|
||||
```
|
||||
|
||||
**Claude's response:**
|
||||
- Creates worktree from `develop` instead of `main`
|
||||
- Adjusts instructions accordingly
|
||||
|
||||
---
|
||||
|
||||
### Example 3: List Current Worktrees
|
||||
|
||||
```
|
||||
User: /worktree
|
||||
```
|
||||
|
||||
**Claude's response:**
|
||||
- Shows usage instructions
|
||||
- Lists example commands
|
||||
- Explains what the command does
|
||||
|
||||
---
|
||||
|
||||
## Customization Options
|
||||
|
||||
### Add Project-Specific Logic
|
||||
|
||||
Modify the template to include project-specific setup:
|
||||
|
||||
```markdown
|
||||
### Step 4: Project Setup
|
||||
|
||||
After creating the worktree, run:
|
||||
|
||||
\`\`\`bash
|
||||
cd {{WORKTREE_PATH}}
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Run database migrations
|
||||
npm run migrate
|
||||
|
||||
# Start dev server
|
||||
npm run dev
|
||||
\`\`\`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Add Team Conventions
|
||||
|
||||
Include your team's specific workflow:
|
||||
|
||||
```markdown
|
||||
### Team Workflow
|
||||
|
||||
1. Create worktree with `/worktree <feature-name>`
|
||||
2. Update Jira ticket status to "In Progress"
|
||||
3. Create draft PR: `gh pr create --draft`
|
||||
4. Develop feature
|
||||
5. Request review when ready
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Add Validation
|
||||
|
||||
Enforce naming conventions:
|
||||
|
||||
```markdown
|
||||
{{#if (not (match args.0 "^(feature|hotfix|refactor|experiment)-"))}}
|
||||
**Error:** Branch name must start with feature-, hotfix-, refactor-, or experiment-
|
||||
|
||||
**Valid examples:**
|
||||
- feature-user-auth
|
||||
- hotfix-login-bug
|
||||
- refactor-api-layer
|
||||
- experiment-new-db
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Command Not Found
|
||||
|
||||
**Problem:** `/worktree` command doesn't appear
|
||||
|
||||
**Solution:**
|
||||
1. Check file location: `.claude/commands/worktree.md`
|
||||
2. Restart Claude Code
|
||||
3. Verify file has correct frontmatter (YAML header with `description`)
|
||||
|
||||
---
|
||||
|
||||
### Script Path Issues
|
||||
|
||||
**Problem:** Scripts not found
|
||||
|
||||
**Solution:**
|
||||
- Use absolute paths: `<skill-path>/scripts/create_worktree.sh`
|
||||
- Or add scripts to PATH
|
||||
- Or check scripts are in correct location
|
||||
|
||||
---
|
||||
|
||||
### Template Variables Not Working
|
||||
|
||||
**Problem:** `{{args.0}}` showing as literal text
|
||||
|
||||
**Solution:**
|
||||
- Ensure proper template syntax
|
||||
- Check Claude Code version (templates require recent version)
|
||||
- Verify YAML frontmatter is correct
|
||||
|
||||
---
|
||||
|
||||
## Complete Example
|
||||
|
||||
Here's a fully working example you can copy directly:
|
||||
|
||||
**File:** `.claude/commands/worktree.md`
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Create a Git worktree for parallel Claude Code development
|
||||
---
|
||||
|
||||
# Git Worktree Manager
|
||||
|
||||
{{#if args.0}}
|
||||
|
||||
## Creating Worktree: {{args.0}}
|
||||
|
||||
I'll help you set up a new Git worktree for parallel development.
|
||||
|
||||
### Quick Setup
|
||||
|
||||
Run this command:
|
||||
|
||||
\`\`\`bash
|
||||
scripts/create_worktree.sh
|
||||
\`\`\`
|
||||
|
||||
When prompted, enter: **{{args.0}}**
|
||||
|
||||
### Next Steps
|
||||
|
||||
1. ✓ Script will create the worktree
|
||||
2. Open new Claude Code window
|
||||
3. Navigate to the new worktree directory
|
||||
4. Run \`/init\` to orient me
|
||||
5. Start development on {{args.0}}!
|
||||
|
||||
### Manual Alternative
|
||||
|
||||
\`\`\`bash
|
||||
# Create worktree
|
||||
git worktree add ../$(basename $(git rev-parse --show-toplevel))-{{args.0}} -b {{args.0}}
|
||||
|
||||
# Open it
|
||||
cd ../$(basename $(git rev-parse --show-toplevel))-{{args.0}}
|
||||
code .
|
||||
\`\`\`
|
||||
|
||||
**Ready to switch?** See you in the new worktree!
|
||||
|
||||
{{else}}
|
||||
|
||||
## Git Worktree Command
|
||||
|
||||
Create a new worktree for parallel development.
|
||||
|
||||
**Usage:**
|
||||
\`\`\`
|
||||
/worktree <branch-name>
|
||||
\`\`\`
|
||||
|
||||
**Examples:**
|
||||
\`\`\`
|
||||
/worktree feature-api
|
||||
/worktree refactor-auth
|
||||
/worktree hotfix-urgent
|
||||
\`\`\`
|
||||
|
||||
**What it does:**
|
||||
- Creates a new Git worktree in a sibling directory
|
||||
- Sets up the branch
|
||||
- Provides setup instructions
|
||||
|
||||
**Manage worktrees:**
|
||||
- List all: \`scripts/list_worktrees.sh\`
|
||||
- Sync with main: \`scripts/sync_worktree.sh\`
|
||||
- Clean up: \`scripts/cleanup_worktrees.sh\`
|
||||
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Benefits of Custom Command
|
||||
|
||||
**Faster workflow:**
|
||||
- Type `/worktree feature-name` instead of manual commands
|
||||
- Consistent setup every time
|
||||
- Team standardization
|
||||
|
||||
**Better documentation:**
|
||||
- Built-in help
|
||||
- Examples always available
|
||||
- Team-specific instructions
|
||||
|
||||
**Claude integration:**
|
||||
- Seamless handoff to new worktree
|
||||
- Context preservation
|
||||
- Guided workflow
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
1. Create `worktree.md` in `.claude/commands/`
|
||||
2. Copy template
|
||||
3. Customize for your team
|
||||
4. Use `/worktree <branch-name>` in Claude Code
|
||||
5. Enjoy streamlined parallel development!
|
||||
|
||||
**Next level:** Share the command template with your team for consistent workflows.
|
||||
513
skills/git-worktrees/references/worktree_commands.md
Normal file
513
skills/git-worktrees/references/worktree_commands.md
Normal file
@@ -0,0 +1,513 @@
|
||||
# Git Worktree Command Reference
|
||||
|
||||
Complete reference for `git worktree` commands.
|
||||
|
||||
---
|
||||
|
||||
## Basic Commands
|
||||
|
||||
### Create a New Worktree
|
||||
|
||||
```bash
|
||||
# Create worktree with new branch
|
||||
git worktree add <path> -b <new-branch>
|
||||
|
||||
# Create worktree from existing branch
|
||||
git worktree add <path> <existing-branch>
|
||||
|
||||
# Create worktree from specific commit
|
||||
git worktree add <path> <commit-hash>
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
# New feature branch
|
||||
git worktree add ../myapp-feature-api -b feature-api
|
||||
|
||||
# Use existing branch
|
||||
git worktree add ../myapp-hotfix hotfix-login
|
||||
|
||||
# From specific commit
|
||||
git worktree add ../myapp-review abc123def
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### List All Worktrees
|
||||
|
||||
```bash
|
||||
# Simple list
|
||||
git worktree list
|
||||
|
||||
# Porcelain format (machine-readable)
|
||||
git worktree list --porcelain
|
||||
|
||||
# With verbose output
|
||||
git worktree list -v
|
||||
```
|
||||
|
||||
**Output format:**
|
||||
```
|
||||
/home/user/myapp abc123 [main]
|
||||
/home/user/myapp-feature-api def456 [feature-api]
|
||||
/home/user/myapp-hotfix 789ghi [hotfix-login]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Remove a Worktree
|
||||
|
||||
```bash
|
||||
# Remove worktree (must be clean)
|
||||
git worktree remove <path>
|
||||
|
||||
# Force remove (even with uncommitted changes)
|
||||
git worktree remove <path> --force
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
# Clean removal
|
||||
git worktree remove ../myapp-feature-api
|
||||
|
||||
# Force removal
|
||||
git worktree remove ../myapp-feature-api --force
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Move a Worktree
|
||||
|
||||
```bash
|
||||
# Move worktree to new location
|
||||
git worktree move <old-path> <new-path>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
git worktree move ../myapp-feature-api ~/projects/myapp-feature-api
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Prune Stale References
|
||||
|
||||
```bash
|
||||
# Clean up references to removed worktrees
|
||||
git worktree prune
|
||||
|
||||
# Dry run (show what would be pruned)
|
||||
git worktree prune --dry-run
|
||||
|
||||
# Verbose output
|
||||
git worktree prune --verbose
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Lock/Unlock Worktrees
|
||||
|
||||
Prevent a worktree from being automatically pruned or removed.
|
||||
|
||||
```bash
|
||||
# Lock a worktree
|
||||
git worktree lock <path>
|
||||
|
||||
# Lock with reason
|
||||
git worktree lock <path> --reason "Long-running task"
|
||||
|
||||
# Unlock a worktree
|
||||
git worktree unlock <path>
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Worktrees on removable drives
|
||||
- Network-mounted worktrees
|
||||
- Long-running background tasks
|
||||
|
||||
---
|
||||
|
||||
### Create Detached HEAD Worktrees
|
||||
|
||||
Useful for reviewing specific commits without creating a branch.
|
||||
|
||||
```bash
|
||||
# Checkout specific commit
|
||||
git worktree add <path> --detach <commit>
|
||||
|
||||
# Short form
|
||||
git worktree add <path> --detach HEAD~5
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Review a specific commit
|
||||
git worktree add ../review-commit --detach abc123def
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Sparse Checkout in Worktrees
|
||||
|
||||
Only check out specific files/directories in a worktree (useful for large repos).
|
||||
|
||||
```bash
|
||||
# Create worktree with sparse-checkout
|
||||
git worktree add <path> <branch>
|
||||
cd <path>
|
||||
git sparse-checkout init
|
||||
git sparse-checkout set <directory1> <directory2>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Only checkout src/ and tests/
|
||||
git worktree add ../myapp-feature-api feature-api
|
||||
cd ../myapp-feature-api
|
||||
git sparse-checkout init
|
||||
git sparse-checkout set src/ tests/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Repair Commands
|
||||
|
||||
### Repair Worktree
|
||||
|
||||
If worktree becomes corrupted or administrative files are damaged.
|
||||
|
||||
```bash
|
||||
# Repair a worktree
|
||||
git worktree repair
|
||||
|
||||
# Repair specific worktree
|
||||
git worktree repair <path>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Set Worktree Defaults
|
||||
|
||||
```bash
|
||||
# Default path for worktrees (relative to repo)
|
||||
git config worktree.guessRemote true
|
||||
|
||||
# Automatically set up remote tracking
|
||||
git config push.default current
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Workflow 1: Parallel Feature Development
|
||||
|
||||
```bash
|
||||
# 1. Create worktree for feature A
|
||||
git worktree add ../repo-feature-a -b feature-a
|
||||
|
||||
# 2. Create worktree for feature B
|
||||
git worktree add ../repo-feature-b -b feature-b
|
||||
|
||||
# 3. Work on both simultaneously
|
||||
# (open each in separate editor/Claude session)
|
||||
|
||||
# 4. When done, merge both
|
||||
git checkout main
|
||||
git merge feature-a
|
||||
git merge feature-b
|
||||
|
||||
# 5. Clean up
|
||||
git worktree remove ../repo-feature-a
|
||||
git worktree remove ../repo-feature-b
|
||||
git branch -d feature-a feature-b
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Workflow 2: Hotfix During Feature Development
|
||||
|
||||
```bash
|
||||
# You're working in a feature worktree
|
||||
cd ../repo-feature-xyz
|
||||
|
||||
# Need to create hotfix
|
||||
cd <main-repo>
|
||||
git worktree add ../repo-hotfix -b hotfix-urgent
|
||||
|
||||
# Fix the bug
|
||||
cd ../repo-hotfix
|
||||
# ... make fixes ...
|
||||
git add .
|
||||
git commit -m "Fix urgent bug"
|
||||
|
||||
# Merge hotfix
|
||||
git checkout main
|
||||
git merge hotfix-urgent
|
||||
git push
|
||||
|
||||
# Continue feature work
|
||||
cd ../repo-feature-xyz
|
||||
# ... continue ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Workflow 3: Code Review Without Switching
|
||||
|
||||
```bash
|
||||
# Create worktree for review
|
||||
git worktree add ../repo-review pr-branch-name
|
||||
|
||||
# Review in separate window
|
||||
cd ../repo-review
|
||||
# ... review code ...
|
||||
|
||||
# Clean up after review
|
||||
cd <main-repo>
|
||||
git worktree remove ../repo-review
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Commands
|
||||
|
||||
### Check Worktree Status
|
||||
|
||||
```bash
|
||||
# List all worktrees with details
|
||||
git worktree list -v
|
||||
|
||||
# Check if directory is a worktree
|
||||
cd <directory>
|
||||
git rev-parse --git-dir
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Find Orphaned Worktrees
|
||||
|
||||
```bash
|
||||
# List worktrees that no longer exist
|
||||
git worktree list --porcelain | grep "^worktree" | awk '{print $2}' | while read dir; do
|
||||
if [ ! -d "$dir" ]; then
|
||||
echo "Orphaned: $dir"
|
||||
fi
|
||||
done
|
||||
|
||||
# Clean them up
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Reset Worktree to Clean State
|
||||
|
||||
```bash
|
||||
# Discard all changes
|
||||
cd <worktree>
|
||||
git reset --hard HEAD
|
||||
git clean -fd
|
||||
|
||||
# Reset to specific branch state
|
||||
git fetch origin
|
||||
git reset --hard origin/<branch>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration with Other Git Commands
|
||||
|
||||
### Fetch/Pull in Worktrees
|
||||
|
||||
```bash
|
||||
# Fetch applies to all worktrees (shared .git)
|
||||
git fetch origin
|
||||
|
||||
# Pull in specific worktree
|
||||
cd <worktree>
|
||||
git pull origin <branch>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Stash in Worktrees
|
||||
|
||||
```bash
|
||||
# Stash is per-worktree
|
||||
cd <worktree>
|
||||
git stash push -m "My stash"
|
||||
|
||||
# List stashes (shared across worktrees)
|
||||
git stash list
|
||||
|
||||
# Apply stash in different worktree
|
||||
cd <other-worktree>
|
||||
git stash apply stash@{0}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Rebase in Worktrees
|
||||
|
||||
```bash
|
||||
# Each worktree can have independent rebase operations
|
||||
cd <worktree>
|
||||
git rebase main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Limit Number of Worktrees
|
||||
|
||||
- **Recommended:** 3-5 active worktrees
|
||||
- **Maximum:** Depends on disk space and RAM
|
||||
- **Why:** Each worktree duplicates working files
|
||||
|
||||
### Use Sparse Checkout
|
||||
|
||||
For large repositories:
|
||||
|
||||
```bash
|
||||
git sparse-checkout set <dir1> <dir2>
|
||||
```
|
||||
|
||||
Reduces disk usage by only checking out necessary files.
|
||||
|
||||
---
|
||||
|
||||
### Share Object Database
|
||||
|
||||
Worktrees automatically share:
|
||||
- `.git/objects/` (commits, trees, blobs)
|
||||
- `.git/refs/` (branches, tags)
|
||||
- `.git/config` (configuration)
|
||||
|
||||
**No duplication of:**
|
||||
- Git history
|
||||
- Commit objects
|
||||
- Branch information
|
||||
|
||||
**Duplicated:**
|
||||
- Working directory files
|
||||
- Index (staging area)
|
||||
- Worktree-specific config
|
||||
|
||||
---
|
||||
|
||||
## Safety and Best Practices
|
||||
|
||||
### Before Removing Worktrees
|
||||
|
||||
```bash
|
||||
# Check for uncommitted changes
|
||||
cd <worktree>
|
||||
git status
|
||||
|
||||
# Check if branch is merged
|
||||
git branch --merged main | grep <branch-name>
|
||||
|
||||
# Backup if needed
|
||||
git stash push -m "Backup before removal"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Handling Merge Conflicts
|
||||
|
||||
```bash
|
||||
# During merge in worktree
|
||||
cd <worktree>
|
||||
git merge main
|
||||
|
||||
# If conflicts occur
|
||||
git status # See conflicting files
|
||||
# Edit files to resolve
|
||||
git add <resolved-files>
|
||||
git commit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Table
|
||||
|
||||
| Command | Purpose | Example |
|
||||
|---------|---------|---------|
|
||||
| `git worktree add <path> -b <branch>` | Create with new branch | `git worktree add ../wt -b feat` |
|
||||
| `git worktree add <path> <branch>` | Create from existing | `git worktree add ../wt main` |
|
||||
| `git worktree list` | Show all worktrees | - |
|
||||
| `git worktree remove <path>` | Remove worktree | `git worktree remove ../wt` |
|
||||
| `git worktree remove <path> --force` | Force remove | `git worktree remove ../wt -f` |
|
||||
| `git worktree prune` | Clean stale refs | - |
|
||||
| `git worktree move <old> <new>` | Move worktree | `git worktree move ../wt ~/wt` |
|
||||
| `git worktree lock <path>` | Prevent pruning | `git worktree lock ../wt` |
|
||||
| `git worktree unlock <path>` | Allow pruning | `git worktree unlock ../wt` |
|
||||
| `git worktree repair` | Fix corrupted worktree | - |
|
||||
|
||||
---
|
||||
|
||||
## Common Error Messages
|
||||
|
||||
### "fatal: '<path>' already exists"
|
||||
|
||||
**Cause:** Directory exists
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
rm -rf <path>
|
||||
# or use a different path
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### "fatal: invalid reference: <branch>"
|
||||
|
||||
**Cause:** Branch name has invalid characters
|
||||
|
||||
**Solution:** Use only alphanumeric and hyphens:
|
||||
```bash
|
||||
# Bad: feature/my_feature
|
||||
# Good: feature-my-feature
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### "fatal: '<path>' is not a working tree"
|
||||
|
||||
**Cause:** Trying to operate on non-worktree directory
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
git worktree list # Find correct path
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### "fatal: '<branch>' is already checked out"
|
||||
|
||||
**Cause:** Branch in use by another worktree
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Use a different branch name
|
||||
git worktree add ../wt -b new-branch-name
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
**Official Documentation:**
|
||||
- https://git-scm.com/docs/git-worktree
|
||||
|
||||
**Pro Git Book:**
|
||||
- Chapter on worktrees: https://git-scm.com/book/en/v2
|
||||
|
||||
**Git Worktree Tutorial:**
|
||||
- https://git-scm.com/docs/git-worktree#_examples
|
||||
252
skills/git-worktrees/scripts/cleanup_worktrees.sh
Executable file
252
skills/git-worktrees/scripts/cleanup_worktrees.sh
Executable file
@@ -0,0 +1,252 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Git Worktree Cleanup
|
||||
# Interactive removal of old/merged worktrees
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
GRAY='\033[0;90m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}✗ Error: Not in a git repository${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
REPO_NAME=$(basename "$REPO_ROOT")
|
||||
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Git Worktree Cleanup Tool ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# Get list of worktrees (excluding main)
|
||||
WORKTREES=$(git worktree list --porcelain | grep -v "^$" | grep -v "^HEAD" | grep -v "^bare")
|
||||
|
||||
if [ -z "$WORKTREES" ]; then
|
||||
echo -e "${YELLOW}No feature worktrees found${NC}"
|
||||
echo "Only the main worktree exists."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Arrays to store worktree info
|
||||
declare -a PATHS
|
||||
declare -a BRANCHES
|
||||
declare -a STATUSES
|
||||
declare -a MERGED_FLAGS
|
||||
COUNT=0
|
||||
|
||||
# Parse worktrees
|
||||
CURRENT_PATH=""
|
||||
CURRENT_BRANCH=""
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [[ $line == worktree* ]]; then
|
||||
CURRENT_PATH=$(echo "$line" | awk '{print $2}')
|
||||
elif [[ $line == branch* ]]; then
|
||||
CURRENT_BRANCH=$(echo "$line" | awk '{print $2}' | sed 's|refs/heads/||')
|
||||
|
||||
# Skip main worktree
|
||||
if [ "$CURRENT_PATH" != "$REPO_ROOT" ] && [ -n "$CURRENT_BRANCH" ]; then
|
||||
PATHS[$COUNT]="$CURRENT_PATH"
|
||||
BRANCHES[$COUNT]="$CURRENT_BRANCH"
|
||||
|
||||
# Check if branch is merged into main
|
||||
cd "$REPO_ROOT"
|
||||
if git branch --merged main | grep -q "^[* ]*${CURRENT_BRANCH}$"; then
|
||||
MERGED_FLAGS[$COUNT]="merged"
|
||||
STATUSES[$COUNT]="${GREEN}✓ Merged to main${NC}"
|
||||
else
|
||||
MERGED_FLAGS[$COUNT]="not-merged"
|
||||
|
||||
# Check if worktree is clean
|
||||
cd "$CURRENT_PATH"
|
||||
if git diff-index --quiet HEAD -- 2>/dev/null; then
|
||||
STATUSES[$COUNT]="${YELLOW}⚠ Not merged, clean${NC}"
|
||||
else
|
||||
CHANGE_COUNT=$(git status --short | wc -l | tr -d ' ')
|
||||
STATUSES[$COUNT]="${RED}⚠ Not merged, $CHANGE_COUNT changes${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
((COUNT++))
|
||||
fi
|
||||
|
||||
CURRENT_PATH=""
|
||||
CURRENT_BRANCH=""
|
||||
fi
|
||||
done <<< "$WORKTREES"
|
||||
|
||||
if [ $COUNT -eq 0 ]; then
|
||||
echo -e "${YELLOW}No feature worktrees to clean up${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Display worktrees
|
||||
echo -e "${CYAN}Found $COUNT feature worktree(s):${NC}"
|
||||
echo ""
|
||||
|
||||
for i in "${!PATHS[@]}"; do
|
||||
echo -e "${CYAN}[$((i+1))]${NC} ${BRANCHES[$i]}"
|
||||
echo -e " Path: ${GRAY}${PATHS[$i]}${NC}"
|
||||
echo -e " Status: ${STATUSES[$i]}"
|
||||
echo ""
|
||||
done
|
||||
|
||||
# Prompt for selection
|
||||
echo -e "${YELLOW}Which worktrees would you like to remove?${NC}"
|
||||
echo -e " Enter numbers separated by spaces (e.g., '1 3 4')"
|
||||
echo -e " Enter 'merged' to remove all merged worktrees"
|
||||
echo -e " Enter 'all' to remove all worktrees"
|
||||
echo -e " Press Enter to cancel"
|
||||
echo ""
|
||||
read -p "Selection: " SELECTION
|
||||
|
||||
# Parse selection
|
||||
if [ -z "$SELECTION" ]; then
|
||||
echo -e "${GRAY}Cancelled${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Build list of indices to remove
|
||||
declare -a TO_REMOVE
|
||||
|
||||
if [ "$SELECTION" = "all" ]; then
|
||||
for i in "${!PATHS[@]}"; do
|
||||
TO_REMOVE+=($i)
|
||||
done
|
||||
elif [ "$SELECTION" = "merged" ]; then
|
||||
for i in "${!PATHS[@]}"; do
|
||||
if [ "${MERGED_FLAGS[$i]}" = "merged" ]; then
|
||||
TO_REMOVE+=($i)
|
||||
fi
|
||||
done
|
||||
if [ ${#TO_REMOVE[@]} -eq 0 ]; then
|
||||
echo -e "${YELLOW}No merged worktrees found${NC}"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
# Parse space-separated numbers
|
||||
for num in $SELECTION; do
|
||||
# Validate number
|
||||
if [[ "$num" =~ ^[0-9]+$ ]] && [ "$num" -ge 1 ] && [ "$num" -le "$COUNT" ]; then
|
||||
TO_REMOVE+=($((num - 1)))
|
||||
else
|
||||
echo -e "${RED}Invalid selection: $num${NC}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Confirmation
|
||||
echo ""
|
||||
echo -e "${YELLOW}About to remove ${#TO_REMOVE[@]} worktree(s):${NC}"
|
||||
echo ""
|
||||
for idx in "${TO_REMOVE[@]}"; do
|
||||
echo -e " ${RED}✗${NC} ${BRANCHES[$idx]}"
|
||||
echo -e " ${GRAY}${PATHS[$idx]}${NC}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Extra warning for non-merged branches
|
||||
HAS_UNMERGED=false
|
||||
for idx in "${TO_REMOVE[@]}"; do
|
||||
if [ "${MERGED_FLAGS[$idx]}" != "merged" ]; then
|
||||
HAS_UNMERGED=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$HAS_UNMERGED" = true ]; then
|
||||
echo -e "${RED}⚠ WARNING: Some branches are NOT merged!${NC}"
|
||||
echo -e "${RED} You may lose uncommitted work.${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
read -p "Are you sure? (yes/no): " CONFIRM
|
||||
|
||||
if [ "$CONFIRM" != "yes" ]; then
|
||||
echo -e "${GRAY}Cancelled${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Remove worktrees
|
||||
echo ""
|
||||
echo -e "${BLUE}Removing worktrees...${NC}"
|
||||
echo ""
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
for idx in "${TO_REMOVE[@]}"; do
|
||||
WORKTREE_PATH="${PATHS[$idx]}"
|
||||
BRANCH_NAME="${BRANCHES[$idx]}"
|
||||
|
||||
echo -e "${CYAN}→${NC} Removing worktree: ${BRANCH_NAME}"
|
||||
|
||||
# Remove worktree
|
||||
if git worktree remove "$WORKTREE_PATH" --force 2>/dev/null; then
|
||||
echo -e " ${GREEN}✓${NC} Worktree removed"
|
||||
else
|
||||
# Try manual removal if git worktree remove fails
|
||||
if [ -d "$WORKTREE_PATH" ]; then
|
||||
rm -rf "$WORKTREE_PATH"
|
||||
git worktree prune
|
||||
echo -e " ${GREEN}✓${NC} Worktree removed (manual cleanup)"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} Worktree already removed"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ask about deleting the branch
|
||||
if [ "${MERGED_FLAGS[$idx]}" = "merged" ]; then
|
||||
# Auto-delete merged branches
|
||||
git branch -d "$BRANCH_NAME" 2>/dev/null && \
|
||||
echo -e " ${GREEN}✓${NC} Branch deleted" || \
|
||||
echo -e " ${GRAY}Branch already deleted or doesn't exist${NC}"
|
||||
else
|
||||
# Prompt for unmerged branches
|
||||
echo -e " ${YELLOW}Branch '$BRANCH_NAME' is not merged.${NC}"
|
||||
read -p " Delete branch anyway? (y/n): " DELETE_BRANCH
|
||||
if [[ "$DELETE_BRANCH" =~ ^[Yy]$ ]]; then
|
||||
git branch -D "$BRANCH_NAME" 2>/dev/null && \
|
||||
echo -e " ${GREEN}✓${NC} Branch force-deleted" || \
|
||||
echo -e " ${GRAY}Could not delete branch${NC}"
|
||||
else
|
||||
echo -e " ${GRAY}Branch kept${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
# Prune any stale references
|
||||
echo -e "${CYAN}→${NC} Cleaning up stale references..."
|
||||
git worktree prune
|
||||
echo -e "${GREEN}✓${NC} Done"
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo -e "${GREEN}✓ Cleanup complete!${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
echo -e "Removed: ${CYAN}${#TO_REMOVE[@]}${NC} worktree(s)"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
|
||||
# Show remaining worktrees
|
||||
REMAINING=$(git worktree list | wc -l)
|
||||
if [ $REMAINING -gt 1 ]; then
|
||||
echo -e "${CYAN}Remaining worktrees: $((REMAINING - 1))${NC}"
|
||||
echo -e "${GRAY}Run 'scripts/list_worktrees.sh' to see them${NC}"
|
||||
else
|
||||
echo -e "${CYAN}No feature worktrees remaining${NC}"
|
||||
fi
|
||||
echo ""
|
||||
211
skills/git-worktrees/scripts/create_worktree.sh
Executable file
211
skills/git-worktrees/scripts/create_worktree.sh
Executable file
@@ -0,0 +1,211 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Git Worktree Creator for Claude Code
|
||||
# Makes creating worktrees super simple with interactive prompts
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Default values
|
||||
BASE_BRANCH="main"
|
||||
CUSTOM_DIR=""
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--base)
|
||||
BASE_BRANCH="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dir)
|
||||
CUSTOM_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --base <branch> Base branch to branch from (default: main)"
|
||||
echo " --dir <path> Custom directory for worktree"
|
||||
echo " -h, --help Show this help"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $0"
|
||||
echo " $0 --base develop"
|
||||
echo " $0 --dir ~/worktrees/my-feature"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Unknown option: $1${NC}"
|
||||
echo "Use -h for help"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Git Worktree Creator for Claude Code ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}✗ Error: Not in a git repository${NC}"
|
||||
echo " Please run this script from within a git repository."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get repository info
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
REPO_NAME=$(basename "$REPO_ROOT")
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
echo -e "${GREEN}✓${NC} Found git repository: ${CYAN}$REPO_NAME${NC}"
|
||||
echo -e "${GREEN}✓${NC} Current branch: ${CYAN}$CURRENT_BRANCH${NC}"
|
||||
echo ""
|
||||
|
||||
# Prompt for feature name
|
||||
echo -e "${YELLOW}What are you building?${NC}"
|
||||
echo -e " Enter a feature name (e.g., feature-api, refactor-auth, hotfix-bug)"
|
||||
echo ""
|
||||
read -p "Feature name: " FEATURE_NAME
|
||||
|
||||
# Validate feature name
|
||||
if [ -z "$FEATURE_NAME" ]; then
|
||||
echo -e "${RED}✗ Feature name cannot be empty${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Sanitize feature name (replace spaces with hyphens, lowercase)
|
||||
FEATURE_NAME=$(echo "$FEATURE_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed 's/[^a-z0-9-]//g')
|
||||
|
||||
if [ -z "$FEATURE_NAME" ]; then
|
||||
echo -e "${RED}✗ Invalid feature name${NC}"
|
||||
echo " Use only letters, numbers, and hyphens"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓${NC} Using branch name: ${CYAN}$FEATURE_NAME${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if branch already exists
|
||||
if git show-ref --verify --quiet "refs/heads/$FEATURE_NAME"; then
|
||||
echo -e "${YELLOW}⚠${NC} Branch ${CYAN}$FEATURE_NAME${NC} already exists"
|
||||
echo ""
|
||||
read -p "Use existing branch? (y/n): " USE_EXISTING
|
||||
if [[ ! "$USE_EXISTING" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${RED}✗ Cancelled${NC}"
|
||||
exit 1
|
||||
fi
|
||||
CREATE_BRANCH=false
|
||||
else
|
||||
# Prompt for base branch
|
||||
echo -e "${YELLOW}Base branch${NC} (press Enter for default: $BASE_BRANCH)"
|
||||
read -p "Base branch: " CUSTOM_BASE
|
||||
if [ -n "$CUSTOM_BASE" ]; then
|
||||
BASE_BRANCH="$CUSTOM_BASE"
|
||||
fi
|
||||
|
||||
# Verify base branch exists
|
||||
if ! git show-ref --verify --quiet "refs/heads/$BASE_BRANCH"; then
|
||||
echo -e "${RED}✗ Base branch '$BASE_BRANCH' does not exist${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓${NC} Will create branch from: ${CYAN}$BASE_BRANCH${NC}"
|
||||
CREATE_BRANCH=true
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Determine worktree directory
|
||||
if [ -n "$CUSTOM_DIR" ]; then
|
||||
WORKTREE_DIR="$CUSTOM_DIR"
|
||||
else
|
||||
# Default: create sibling directory
|
||||
PARENT_DIR=$(dirname "$REPO_ROOT")
|
||||
WORKTREE_DIR="$PARENT_DIR/${REPO_NAME}-${FEATURE_NAME}"
|
||||
fi
|
||||
|
||||
# Check if directory already exists
|
||||
if [ -d "$WORKTREE_DIR" ]; then
|
||||
echo -e "${RED}✗ Directory already exists: $WORKTREE_DIR${NC}"
|
||||
echo " Please remove it first or use --dir to specify a different location"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}Creating worktree...${NC}"
|
||||
echo ""
|
||||
echo -e " ${CYAN}Branch:${NC} $FEATURE_NAME"
|
||||
echo -e " ${CYAN}Location:${NC} $WORKTREE_DIR"
|
||||
echo ""
|
||||
|
||||
# Create the worktree
|
||||
if [ "$CREATE_BRANCH" = true ]; then
|
||||
echo -e "${CYAN}→${NC} Creating branch from $BASE_BRANCH..."
|
||||
git worktree add -b "$FEATURE_NAME" "$WORKTREE_DIR" "$BASE_BRANCH"
|
||||
else
|
||||
echo -e "${CYAN}→${NC} Using existing branch $FEATURE_NAME..."
|
||||
git worktree add "$WORKTREE_DIR" "$FEATURE_NAME"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ Worktree created successfully!${NC}"
|
||||
echo ""
|
||||
|
||||
# Success message with instructions
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Next Steps ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}1. Open Claude Code in the new worktree:${NC}"
|
||||
echo -e " ${YELLOW}cd $WORKTREE_DIR${NC}"
|
||||
echo -e " ${YELLOW}code .${NC} (or your editor command)"
|
||||
echo ""
|
||||
echo -e "${CYAN}2. In Claude Code, run /init to orient Claude:${NC}"
|
||||
echo -e " ${YELLOW}/init${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}3. Give Claude your task:${NC}"
|
||||
echo -e " ${YELLOW}\"Build the $FEATURE_NAME feature\"${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}4. When done, merge back to main:${NC}"
|
||||
echo -e " ${YELLOW}cd $REPO_ROOT${NC}"
|
||||
echo -e " ${YELLOW}git checkout main${NC}"
|
||||
echo -e " ${YELLOW}git merge $FEATURE_NAME${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}5. Clean up the worktree:${NC}"
|
||||
echo -e " ${YELLOW}scripts/cleanup_worktrees.sh${NC}"
|
||||
echo ""
|
||||
|
||||
# Offer to open in editor
|
||||
echo ""
|
||||
read -p "Open in VS Code now? (y/n): " OPEN_NOW
|
||||
if [[ "$OPEN_NOW" =~ ^[Yy]$ ]]; then
|
||||
if command -v code &> /dev/null; then
|
||||
echo -e "${CYAN}→${NC} Opening in VS Code..."
|
||||
code "$WORKTREE_DIR"
|
||||
echo -e "${GREEN}✓${NC} VS Code opened!"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Remember to run /init when Claude Code loads!${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠${NC} VS Code command 'code' not found"
|
||||
echo " Please open manually: $WORKTREE_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ Done!${NC}"
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
echo -e "Worktree: ${CYAN}$WORKTREE_DIR${NC}"
|
||||
echo -e "Branch: ${CYAN}$FEATURE_NAME${NC}"
|
||||
echo -e "Status: ${GREEN}Ready for Claude Code${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
117
skills/git-worktrees/scripts/list_worktrees.sh
Executable file
117
skills/git-worktrees/scripts/list_worktrees.sh
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
|
||||
# List Git Worktrees
|
||||
# Shows all active worktrees with clean formatting
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
GRAY='\033[0;90m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}✗ Error: Not in a git repository${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
REPO_NAME=$(basename "$REPO_ROOT")
|
||||
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Git Worktrees - $REPO_NAME"
|
||||
printf "${BLUE}║${NC}"
|
||||
printf "%*s${BLUE}║${NC}\n" $((47 - ${#REPO_NAME})) ""
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# Get worktree list
|
||||
WORKTREES=$(git worktree list --porcelain)
|
||||
|
||||
if [ -z "$WORKTREES" ]; then
|
||||
echo -e "${YELLOW}No worktrees found${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Parse and display worktrees
|
||||
MAIN_WORKTREE=""
|
||||
FEATURE_WORKTREES=""
|
||||
WORKTREE_COUNT=0
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [[ $line == worktree* ]]; then
|
||||
CURRENT_PATH=$(echo "$line" | awk '{print $2}')
|
||||
elif [[ $line == branch* ]]; then
|
||||
CURRENT_BRANCH=$(echo "$line" | awk '{print $2}' | sed 's|refs/heads/||')
|
||||
elif [[ $line == "" ]]; then
|
||||
# End of worktree block
|
||||
if [ -n "$CURRENT_PATH" ]; then
|
||||
((WORKTREE_COUNT++))
|
||||
|
||||
# Get status
|
||||
cd "$CURRENT_PATH"
|
||||
if git diff-index --quiet HEAD -- 2>/dev/null; then
|
||||
STATUS="${GREEN}clean${NC}"
|
||||
else
|
||||
CHANGE_COUNT=$(git status --short | wc -l | tr -d ' ')
|
||||
STATUS="${YELLOW}$CHANGE_COUNT uncommitted changes${NC}"
|
||||
fi
|
||||
|
||||
# Get last commit info
|
||||
LAST_COMMIT=$(git log -1 --format="%cr" 2>/dev/null || echo "no commits")
|
||||
|
||||
# Check if it's the main worktree
|
||||
if [ "$CURRENT_PATH" = "$REPO_ROOT" ]; then
|
||||
MAIN_WORKTREE+="📁 ${CYAN}Main Worktree${NC}\n"
|
||||
MAIN_WORKTREE+=" Path: ${GRAY}$CURRENT_PATH${NC}\n"
|
||||
MAIN_WORKTREE+=" Branch: ${CYAN}$CURRENT_BRANCH${NC}\n"
|
||||
MAIN_WORKTREE+=" Status: $STATUS\n"
|
||||
MAIN_WORKTREE+=" Last: ${GRAY}$LAST_COMMIT${NC}\n"
|
||||
else
|
||||
FEATURE_WORKTREES+="📦 ${CYAN}$CURRENT_BRANCH${NC}\n"
|
||||
FEATURE_WORKTREES+=" Path: ${GRAY}$CURRENT_PATH${NC}\n"
|
||||
FEATURE_WORKTREES+=" Status: $STATUS\n"
|
||||
FEATURE_WORKTREES+=" Last: ${GRAY}$LAST_COMMIT${NC}\n\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Reset for next worktree
|
||||
CURRENT_PATH=""
|
||||
CURRENT_BRANCH=""
|
||||
fi
|
||||
done <<< "$WORKTREES"
|
||||
|
||||
# Display main worktree
|
||||
if [ -n "$MAIN_WORKTREE" ]; then
|
||||
echo -e "$MAIN_WORKTREE"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Display feature worktrees
|
||||
if [ -n "$FEATURE_WORKTREES" ]; then
|
||||
echo -e "${BLUE}Feature Worktrees:${NC}"
|
||||
echo ""
|
||||
echo -e "$FEATURE_WORKTREES"
|
||||
else
|
||||
echo -e "${GRAY}No feature worktrees (only main)${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
echo -e "Total worktrees: ${CYAN}$WORKTREE_COUNT${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
|
||||
# Tips
|
||||
if [ $WORKTREE_COUNT -gt 1 ]; then
|
||||
echo -e "${GRAY}Tip: Run 'scripts/cleanup_worktrees.sh' to remove old worktrees${NC}"
|
||||
else
|
||||
echo -e "${GRAY}Tip: Run 'scripts/create_worktree.sh' to create a new worktree${NC}"
|
||||
fi
|
||||
echo ""
|
||||
232
skills/git-worktrees/scripts/sync_worktree.sh
Executable file
232
skills/git-worktrees/scripts/sync_worktree.sh
Executable file
@@ -0,0 +1,232 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Git Worktree Sync
|
||||
# Keep worktree branch up-to-date with main branch
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
GRAY='\033[0;90m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Default values
|
||||
TARGET_WORKTREE=""
|
||||
BASE_BRANCH="main"
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--base)
|
||||
BASE_BRANCH="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
echo "Usage: $0 [WORKTREE_PATH] [OPTIONS]"
|
||||
echo ""
|
||||
echo "Syncs a worktree with the latest changes from main (or specified base branch)."
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " WORKTREE_PATH Path to worktree (optional if run from within worktree)"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --base <branch> Base branch to sync from (default: main)"
|
||||
echo " -h, --help Show this help"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " # From within a worktree"
|
||||
echo " $0"
|
||||
echo ""
|
||||
echo " # Specify worktree path"
|
||||
echo " $0 ../repo-feature-api"
|
||||
echo ""
|
||||
echo " # Sync from develop instead of main"
|
||||
echo " $0 --base develop"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
TARGET_WORKTREE="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Git Worktree Sync Tool ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}✗ Error: Not in a git repository${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine target worktree
|
||||
if [ -z "$TARGET_WORKTREE" ]; then
|
||||
# Use current directory
|
||||
TARGET_WORKTREE=$(pwd)
|
||||
echo -e "${CYAN}→${NC} Using current directory"
|
||||
else
|
||||
# Use specified path
|
||||
if [ ! -d "$TARGET_WORKTREE" ]; then
|
||||
echo -e "${RED}✗ Error: Directory not found: $TARGET_WORKTREE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
cd "$TARGET_WORKTREE"
|
||||
echo -e "${CYAN}→${NC} Using specified worktree: $TARGET_WORKTREE"
|
||||
fi
|
||||
|
||||
# Verify we're in a git worktree
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}✗ Error: Not a git worktree: $TARGET_WORKTREE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
REPO_NAME=$(basename "$REPO_ROOT")
|
||||
|
||||
echo -e "${GREEN}✓${NC} Repository: ${CYAN}$REPO_NAME${NC}"
|
||||
echo -e "${GREEN}✓${NC} Current branch: ${CYAN}$CURRENT_BRANCH${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if current branch is the base branch
|
||||
if [ "$CURRENT_BRANCH" = "$BASE_BRANCH" ]; then
|
||||
echo -e "${YELLOW}⚠${NC} You're on the base branch ($BASE_BRANCH)"
|
||||
echo " Nothing to sync!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check for uncommitted changes
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
echo -e "${YELLOW}⚠ Warning: You have uncommitted changes${NC}"
|
||||
echo ""
|
||||
git status --short
|
||||
echo ""
|
||||
read -p "Stash changes and continue? (y/n): " STASH_CHANGES
|
||||
if [[ ! "$STASH_CHANGES" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${GRAY}Cancelled${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${CYAN}→${NC} Stashing changes..."
|
||||
git stash push -m "Auto-stash before sync at $(date)"
|
||||
STASHED=true
|
||||
echo -e "${GREEN}✓${NC} Changes stashed"
|
||||
echo ""
|
||||
else
|
||||
STASHED=false
|
||||
fi
|
||||
|
||||
# Fetch latest
|
||||
echo -e "${CYAN}→${NC} Fetching latest from remote..."
|
||||
git fetch origin
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}✗ Failed to fetch from remote${NC}"
|
||||
if [ "$STASHED" = true ]; then
|
||||
echo -e "${CYAN}→${NC} Restoring stashed changes..."
|
||||
git stash pop
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓${NC} Fetched latest"
|
||||
echo ""
|
||||
|
||||
# Check if base branch exists locally
|
||||
if ! git show-ref --verify --quiet "refs/heads/$BASE_BRANCH"; then
|
||||
echo -e "${RED}✗ Base branch '$BASE_BRANCH' does not exist locally${NC}"
|
||||
if [ "$STASHED" = true ]; then
|
||||
echo -e "${CYAN}→${NC} Restoring stashed changes..."
|
||||
git stash pop
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Show what we're about to do
|
||||
BEHIND_COUNT=$(git rev-list --count HEAD..origin/$BASE_BRANCH 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$BEHIND_COUNT" = "0" ]; then
|
||||
echo -e "${GREEN}✓${NC} Already up-to-date with $BASE_BRANCH!"
|
||||
if [ "$STASHED" = true ]; then
|
||||
echo ""
|
||||
echo -e "${CYAN}→${NC} Restoring stashed changes..."
|
||||
git stash pop
|
||||
echo -e "${GREEN}✓${NC} Changes restored"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Your branch is $BEHIND_COUNT commit(s) behind $BASE_BRANCH${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}Recent commits in $BASE_BRANCH:${NC}"
|
||||
git log --oneline HEAD..origin/$BASE_BRANCH | head -5
|
||||
echo ""
|
||||
|
||||
read -p "Merge $BASE_BRANCH into $CURRENT_BRANCH? (y/n): " CONFIRM_MERGE
|
||||
if [[ ! "$CONFIRM_MERGE" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${GRAY}Cancelled${NC}"
|
||||
if [ "$STASHED" = true ]; then
|
||||
echo -e "${CYAN}→${NC} Restoring stashed changes..."
|
||||
git stash pop
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Perform the merge
|
||||
echo ""
|
||||
echo -e "${CYAN}→${NC} Merging $BASE_BRANCH into $CURRENT_BRANCH..."
|
||||
|
||||
if git merge origin/$BASE_BRANCH -m "Merge $BASE_BRANCH into $CURRENT_BRANCH"; then
|
||||
echo -e "${GREEN}✓${NC} Merge successful!"
|
||||
|
||||
# Show summary
|
||||
echo ""
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
echo -e "Branch: ${CYAN}$CURRENT_BRANCH${NC}"
|
||||
echo -e "Status: ${GREEN}Synced with $BASE_BRANCH${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════${NC}"
|
||||
|
||||
# Restore stashed changes if any
|
||||
if [ "$STASHED" = true ]; then
|
||||
echo ""
|
||||
echo -e "${CYAN}→${NC} Restoring stashed changes..."
|
||||
if git stash pop; then
|
||||
echo -e "${GREEN}✓${NC} Changes restored successfully"
|
||||
else
|
||||
echo -e "${RED}✗${NC} Conflicts while restoring stashed changes"
|
||||
echo " Resolve conflicts manually, then run: git stash drop"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ Sync complete!${NC}"
|
||||
echo ""
|
||||
|
||||
else
|
||||
# Merge failed (likely conflicts)
|
||||
echo -e "${RED}✗ Merge conflicts detected${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Conflicting files:${NC}"
|
||||
git diff --name-only --diff-filter=U
|
||||
echo ""
|
||||
echo -e "${CYAN}To resolve:${NC}"
|
||||
echo " 1. Fix conflicts in the files above"
|
||||
echo " 2. Stage resolved files: ${YELLOW}git add <file>${NC}"
|
||||
echo " 3. Complete the merge: ${YELLOW}git commit${NC}"
|
||||
|
||||
if [ "$STASHED" = true ]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Note: Stashed changes will be restored after merge is complete${NC}"
|
||||
echo " Run: ${YELLOW}git stash pop${NC}"
|
||||
fi
|
||||
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user