Merge pull request #27 from skinnyandbald/fix/git-worktree-env-copy

fix(git-worktree): auto-copy .env files when creating worktrees
This commit is contained in:
Kieran Klaassen
2025-12-02 15:17:15 -08:00
committed by GitHub
2 changed files with 146 additions and 26 deletions

View File

@@ -15,6 +15,24 @@ This skill provides a unified interface for managing Git worktrees across your d
- **Clean up completed worktrees** automatically - **Clean up completed worktrees** automatically
- **Interactive confirmations** at each step - **Interactive confirmations** at each step
- **Automatic .gitignore management** for worktree directory - **Automatic .gitignore management** for worktree directory
- **Automatic .env file copying** from main repo to new worktrees
## CRITICAL: Always Use the Manager Script
**NEVER call `git worktree add` directly.** Always use the `worktree-manager.sh` script.
The script handles critical setup that raw git commands don't:
1. Copies `.env`, `.env.local`, `.env.test`, etc. from main repo
2. Ensures `.worktrees` is in `.gitignore`
3. Creates consistent directory structure
```bash
# ✅ CORRECT - Always use the script
bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh create feature-name
# ❌ WRONG - Never do this directly
git worktree add .worktrees/feature-name -b feature-name main
```
## When to Use This Skill ## When to Use This Skill
@@ -41,17 +59,20 @@ The skill is automatically called from `/review` and `/work` commands:
You can also invoke the skill directly from bash: You can also invoke the skill directly from bash:
```bash ```bash
# Create a new worktree # Create a new worktree (copies .env files automatically)
bash .claude/skills/git-worktree/scripts/worktree-manager.sh create feature-login bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh create feature-login
# List all worktrees # List all worktrees
bash .claude/skills/git-worktree/scripts/worktree-manager.sh list bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh list
# Switch to a worktree # Switch to a worktree
bash .claude/skills/git-worktree/scripts/worktree-manager.sh switch feature-login bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh switch feature-login
# Copy .env files to an existing worktree (if they weren't copied)
bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh copy-env feature-login
# Clean up completed worktrees # Clean up completed worktrees
bash .claude/skills/git-worktree/scripts/worktree-manager.sh cleanup bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh cleanup
``` ```
## Commands ## Commands
@@ -66,14 +87,15 @@ Creates a new worktree with the given branch name.
**Example:** **Example:**
```bash ```bash
bash .claude/skills/git-worktree/scripts/worktree-manager.sh create feature-login bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh create feature-login
``` ```
**What happens:** **What happens:**
1. Checks if worktree already exists 1. Checks if worktree already exists
2. Updates the base branch from remote 2. Updates the base branch from remote
3. Creates new worktree and branch 3. Creates new worktree and branch
4. Shows path for cd-ing to the worktree 4. **Copies all .env files from main repo** (.env, .env.local, .env.test, etc.)
5. Shows path for cd-ing to the worktree
### `list` or `ls` ### `list` or `ls`
@@ -81,7 +103,7 @@ Lists all available worktrees with their branches and current status.
**Example:** **Example:**
```bash ```bash
bash .claude/skills/git-worktree/scripts/worktree-manager.sh list bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh list
``` ```
**Output shows:** **Output shows:**
@@ -96,7 +118,7 @@ Switches to an existing worktree and cd's into it.
**Example:** **Example:**
```bash ```bash
bash .claude/skills/git-worktree/scripts/worktree-manager.sh switch feature-login bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh switch feature-login
``` ```
**Optional:** **Optional:**
@@ -108,7 +130,7 @@ Interactively cleans up inactive worktrees with confirmation.
**Example:** **Example:**
```bash ```bash
bash .claude/skills/git-worktree/scripts/worktree-manager.sh cleanup bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh cleanup
``` ```
**What happens:** **What happens:**
@@ -126,35 +148,35 @@ bash .claude/skills/git-worktree/scripts/worktree-manager.sh cleanup
# Offers: "Use worktree for isolated review? (y/n)" # Offers: "Use worktree for isolated review? (y/n)"
# You respond: yes # You respond: yes
# Script runs: # Script runs (copies .env files automatically):
bash .claude/skills/git-worktree/scripts/worktree-manager.sh create pr-123-feature-name bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh create pr-123-feature-name
# You're now in isolated worktree for review # You're now in isolated worktree for review with all env vars
cd .worktrees/pr-123-feature-name cd .worktrees/pr-123-feature-name
# After review, return to main: # After review, return to main:
cd ../.. cd ../..
bash .claude/skills/git-worktree/scripts/worktree-manager.sh cleanup bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh cleanup
``` ```
### Parallel Feature Development ### Parallel Feature Development
```bash ```bash
# For first feature: # For first feature (copies .env files):
bash .claude/skills/git-worktree/scripts/worktree-manager.sh create feature-login bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh create feature-login
# Later, start second feature: # Later, start second feature (also copies .env files):
bash .claude/skills/git-worktree/scripts/worktree-manager.sh create feature-notifications bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh create feature-notifications
# List what you have: # List what you have:
bash .claude/skills/git-worktree/scripts/worktree-manager.sh list bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh list
# Switch between them as needed: # Switch between them as needed:
bash .claude/skills/git-worktree/scripts/worktree-manager.sh switch feature-login bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh switch feature-login
# Return to main and cleanup when done: # Return to main and cleanup when done:
cd . cd .
bash .claude/skills/git-worktree/scripts/worktree-manager.sh cleanup bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh cleanup
``` ```
## Key Design Principles ## Key Design Principles
@@ -216,11 +238,11 @@ If you see this, the script will ask if you want to switch to it instead.
### "Cannot remove worktree: it is the current worktree" ### "Cannot remove worktree: it is the current worktree"
Switch out of the worktree first, then cleanup: Switch out of the worktree first (to main repo), then cleanup:
```bash ```bash
cd /Users/kieranklaassen/rails/cora cd $(git rev-parse --show-toplevel)
bash .claude/skills/git-worktree/scripts/worktree-manager.sh cleanup bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh cleanup
``` ```
### Lost in a worktree? ### Lost in a worktree?
@@ -228,7 +250,15 @@ bash .claude/skills/git-worktree/scripts/worktree-manager.sh cleanup
See where you are: See where you are:
```bash ```bash
bash .claude/skills/git-worktree/scripts/worktree-manager.sh list bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh list
```
### .env files missing in worktree?
If a worktree was created without .env files (e.g., via raw `git worktree add`), copy them:
```bash
bash ${CLAUDE_PLUGIN_ROOT}/skills/git-worktree/scripts/worktree-manager.sh copy-env feature-name
``` ```
Navigate back to main: Navigate back to main:

View File

@@ -24,6 +24,47 @@ ensure_gitignore() {
fi fi
} }
# Copy .env files from main repo to worktree
copy_env_files() {
local worktree_path="$1"
echo -e "${BLUE}Copying environment files...${NC}"
# Find all .env* files in root (excluding .env.example which should be in git)
local env_files=()
for f in "$GIT_ROOT"/.env*; do
if [[ -f "$f" ]]; then
local basename=$(basename "$f")
# Skip .env.example (that's typically committed to git)
if [[ "$basename" != ".env.example" ]]; then
env_files+=("$basename")
fi
fi
done
if [[ ${#env_files[@]} -eq 0 ]]; then
echo -e " ${YELLOW} No .env files found in main repository${NC}"
return
fi
local copied=0
for env_file in "${env_files[@]}"; do
local source="$GIT_ROOT/$env_file"
local dest="$worktree_path/$env_file"
if [[ -f "$dest" ]]; then
echo -e " ${YELLOW}⚠️ $env_file already exists, backing up to ${env_file}.backup${NC}"
cp "$dest" "${dest}.backup"
fi
cp "$source" "$dest"
echo -e " ${GREEN}✓ Copied $env_file${NC}"
copied=$((copied + 1))
done
echo -e " ${GREEN}✓ Copied $copied environment file(s)${NC}"
}
# Create a new worktree # Create a new worktree
create_worktree() { create_worktree() {
local branch_name="$1" local branch_name="$1"
@@ -71,6 +112,9 @@ create_worktree() {
echo -e "${BLUE}Creating worktree...${NC}" echo -e "${BLUE}Creating worktree...${NC}"
git worktree add -b "$branch_name" "$worktree_path" "$from_branch" git worktree add -b "$branch_name" "$worktree_path" "$from_branch"
# Copy environment files
copy_env_files "$worktree_path"
echo -e "${GREEN}✓ Worktree created successfully!${NC}" echo -e "${GREEN}✓ Worktree created successfully!${NC}"
echo "" echo ""
echo "To switch to this worktree:" echo "To switch to this worktree:"
@@ -141,6 +185,38 @@ switch_worktree() {
echo -e "${BLUE}Now in: $(pwd)${NC}" echo -e "${BLUE}Now in: $(pwd)${NC}"
} }
# Copy env files to an existing worktree (or current directory if in a worktree)
copy_env_to_worktree() {
local worktree_name="$1"
local worktree_path
if [[ -z "$worktree_name" ]]; then
# Check if we're currently in a worktree
local current_dir=$(pwd)
if [[ "$current_dir" == "$WORKTREE_DIR"/* ]]; then
worktree_path="$current_dir"
worktree_name=$(basename "$worktree_path")
echo -e "${BLUE}Detected current worktree: $worktree_name${NC}"
else
echo -e "${YELLOW}Usage: worktree-manager.sh copy-env [worktree-name]${NC}"
echo "Or run from within a worktree to copy to current directory"
list_worktrees
return 1
fi
else
worktree_path="$WORKTREE_DIR/$worktree_name"
if [[ ! -d "$worktree_path" ]]; then
echo -e "${RED}Error: Worktree not found: $worktree_name${NC}"
list_worktrees
return 1
fi
fi
copy_env_files "$worktree_path"
echo ""
}
# Clean up completed worktrees # Clean up completed worktrees
cleanup_worktrees() { cleanup_worktrees() {
if [[ ! -d "$WORKTREE_DIR" ]]; then if [[ ! -d "$WORKTREE_DIR" ]]; then
@@ -213,6 +289,9 @@ main() {
switch|go) switch|go)
switch_worktree "$2" switch_worktree "$2"
;; ;;
copy-env|env)
copy_env_to_worktree "$2"
;;
cleanup|clean) cleanup|clean)
cleanup_worktrees cleanup_worktrees
;; ;;
@@ -235,16 +314,27 @@ Git Worktree Manager
Usage: worktree-manager.sh <command> [options] Usage: worktree-manager.sh <command> [options]
Commands: Commands:
create <branch-name> [from-branch] Create new worktree create <branch-name> [from-branch] Create new worktree (copies .env files automatically)
(from-branch defaults to main) (from-branch defaults to main)
list | ls List all worktrees list | ls List all worktrees
switch | go [name] Switch to worktree switch | go [name] Switch to worktree
copy-env | env [name] Copy .env files from main repo to worktree
(if name omitted, uses current worktree)
cleanup | clean Clean up inactive worktrees cleanup | clean Clean up inactive worktrees
help Show this help message help Show this help message
Environment Files:
- Automatically copies .env, .env.local, .env.test, etc. on create
- Skips .env.example (should be in git)
- Creates .backup files if destination already exists
- Use 'copy-env' to refresh env files after main repo changes
Examples: Examples:
worktree-manager.sh create feature-login worktree-manager.sh create feature-login
worktree-manager.sh create feature-auth develop
worktree-manager.sh switch feature-login worktree-manager.sh switch feature-login
worktree-manager.sh copy-env feature-login
worktree-manager.sh copy-env # copies to current worktree
worktree-manager.sh cleanup worktree-manager.sh cleanup
worktree-manager.sh list worktree-manager.sh list