Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ git config --add gtr.copy.exclude "**/.env"
./bin/gtr new test-copy
# Expected: Copies .env.example but not .env

# Test .worktreeinclude file
printf '# Test patterns\n**/.env.example\n*.md\n' > .worktreeinclude
echo "TEST=value" > .env.example
./bin/gtr new test-worktreeinclude
# Expected: Copies .env.example and *.md files to worktree
ls "$(./bin/gtr go test-worktreeinclude)/.env.example"
./bin/gtr rm test-worktreeinclude
rm .worktreeinclude .env.example

# Test directory copying with include/exclude patterns
git config --add gtr.copy.includeDirs "node_modules"
git config --add gtr.copy.excludeDirs "node_modules/.cache"
Expand Down Expand Up @@ -402,6 +411,7 @@ All config keys use `gtr.*` prefix and are managed via `git config`:
- `gtr.ai.default`: Default AI tool (aider, claude, codex, etc.)
- `gtr.copy.include`: Multi-valued glob patterns for files to copy
- `gtr.copy.exclude`: Multi-valued glob patterns for files to exclude
- `.worktreeinclude`: File in repo root with glob patterns (merged with `gtr.copy.include`)
- `gtr.copy.includeDirs`: Multi-valued directory patterns to copy (e.g., "node_modules", ".venv", "vendor")
- `gtr.copy.excludeDirs`: Multi-valued directory patterns to exclude when copying (supports globs like "node_modules/.cache", "\*/.cache")
- `gtr.hook.postCreate`: Multi-valued commands to run after creating worktree
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,21 @@ git gtr config add gtr.copy.exclude "**/.env"
git gtr config add gtr.copy.exclude "**/secrets.*"
```

#### Using .worktreeinclude file

Alternatively, create a `.worktreeinclude` file in your repository root:

```gitignore
# .worktreeinclude - files to copy to new worktrees
# Comments start with #

**/.env.example
**/CLAUDE.md
*.config.js
```

The file uses `.gitignore`-style syntax (one pattern per line, `#` for comments, empty lines ignored). Patterns from `.worktreeinclude` are merged with `gtr.copy.include` config settings - both sources are used together.

#### Security Best Practices

**The key distinction:** Development secrets (test API keys, local DB passwords) are **low risk** on personal machines. Production credentials are **high risk** everywhere.
Expand Down
14 changes: 13 additions & 1 deletion bin/gtr
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,22 @@ cmd_create() {

# Copy files based on patterns
if [ "$skip_copy" -eq 0 ]; then
local includes excludes
local includes excludes file_includes
includes=$(cfg_get_all gtr.copy.include)
excludes=$(cfg_get_all gtr.copy.exclude)

# Read .worktreeinclude file if exists
file_includes=$(parse_pattern_file "$repo_root/.worktreeinclude")

# Merge patterns (newline-separated)
if [ -n "$file_includes" ]; then
if [ -n "$includes" ]; then
includes="$includes"$'\n'"$file_includes"
else
includes="$file_includes"
fi
fi

if [ -n "$includes" ]; then
log_step "Copying files..."
copy_patterns "$repo_root" "$worktree_path" "$includes" "$excludes"
Expand Down
14 changes: 14 additions & 0 deletions lib/copy.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#!/usr/bin/env bash
# File copying utilities with pattern matching

# Parse .gitignore-style pattern file
# Usage: parse_pattern_file file_path
# Returns: newline-separated patterns (comments and empty lines stripped)
parse_pattern_file() {
local file_path="$1"

if [ ! -f "$file_path" ]; then
return 0
fi

# Read file, strip comments and empty lines
grep -v '^#' "$file_path" 2>/dev/null | grep -v '^[[:space:]]*$' || true
}

# Copy files matching patterns from source to destination
# Usage: copy_patterns src_root dst_root includes excludes [preserve_paths]
# includes: newline-separated glob patterns to include
Expand Down