feat: add copy command for syncing files between worktrees#39
Conversation
WalkthroughAdds a new git-gtr "copy" subcommand to copy files between worktrees, with --from, -n/--dry-run, -a/--all options; implements per-target copying (dry-run supported), worktree listing helper, updated shell completions, and documentation/examples. Changes
Sequence DiagramsequenceDiagram
actor User
participant CLI as bin/gtr (cmd_copy)
participant Core as lib/core.sh (list_worktree_branches)
participant Copy as lib/copy.sh (copy_patterns)
User->>CLI: git gtr copy --from <src> [-n] [-a] [targets...]
CLI->>CLI: parse flags, load include/exclude patterns
alt --all present
CLI->>Core: list_worktree_branches(repo_root, prefix)
Core-->>CLI: branch list
else targets provided
CLI->>CLI: validate/resolve targets
end
CLI->>CLI: build final target list
loop for each target
CLI->>Copy: copy_patterns(src, dst, patterns, dry_run?)
Copy-->>CLI: per-target logs / copied_count
CLI->>CLI: report per-target status
end
CLI-->>User: aggregated summary (and warnings if nothing copied)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–30 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (5)lib/**/*.sh📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.sh📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.{bash,fish,sh}📄 CodeRabbit inference engine (.github/instructions/sh.instructions.md)
Files:
{bin/gtr,lib/**/*.sh,adapters/**/*.sh}📄 CodeRabbit inference engine (.github/instructions/testing.instructions.md)
Files:
bin/gtr📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
🔇 Additional comments (4)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
lib/core.sh (1)
440-456: Minor cleanup inlist_worktree_branchesand note on semantics
repo_rootis currently unused; either drop it from the signature or rename to_repo_rootto avoid confusion / shellcheck noise.- The helper returns only branch names, which is fine given
resolve_targetis branch‑based, but it also meanscmd_copy --allinherits the existing limitation that you can’t distinguish multiple worktrees sharing the same branch. If you ever add per‑worktree identifiers, this function will likely need to return paths (or path+branch) instead of just names.bin/gtr (1)
81-83:cmd_copyimplementation and wiring look solid
- Dispatcher correctly adds
copy→cmd_copyand the help text matches the implemented flags and examples.- Argument parsing in
cmd_copyis consistent with existing commands:
--from,-n/--dry-run,-a/--all, and--for patterns are handled clearly.- Targets are required unless
--allis set, and repo context / source worktree resolution are guarded with|| exit 1, which is good under globalset -e.- Pattern resolution honors precedence as documented:
- CLI
-- <pattern>...wins overgtr.copy.includeand.worktreeinclude.- Excludes are taken from
gtr.copy.exclude.--allis implemented vialist_worktree_branches, then each target goes throughresolve_target, with source==destination safely skipped and a final warning when nothing is processed.- Dry‑run is correctly plumbed through to
copy_patternsvia the extra boolean parameter, and the logs clearly distinguish real copies from previews.If you later introduce a notion of multiple managed worktrees per branch, note that
cmd_copy --all(likego/run/rm) is inherently branch‑centric viaresolve_targetand would need revisiting to operate per physical worktree instead of per branch.Also applies to: 473-595, 1192-1205
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
bin/gtr(3 hunks)completions/_git-gtr(3 hunks)completions/gtr.bash(2 hunks)completions/gtr.fish(3 hunks)lib/copy.sh(4 hunks)lib/core.sh(1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
lib/**/*.sh
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
lib/**/*.sh: Core libraries (lib/core.sh,lib/config.sh,lib/ui.sh,lib/copy.sh,lib/hooks.sh,lib/platform.sh) must be sourced at startup and implement specific functionality
Maintain backwards compatibility with Git <2.22 by using fallbackrev-parse --abbrev-ref HEADinstead ofbranch --show-current
lib/**/*.sh: Maintain backwards compatibility with existing configs in shell scripts
Quote all paths to support spaces in directory names
Uselog_error/log_infofromlib/ui.shfor user messages
Implement Git version fallbacks (e.g., Git 2.22+--show-currentvs olderrev-parse); checklib/core.sh:97-100for example
Add new config keys withgtr.<name>prefix to avoid collisions
For performance-sensitive loops (e.g., directory scans), prefer built-ins (find,grep) with minimal subshells
For any new Git command, add fallback for older versions or guard with detection
Files:
lib/core.shlib/copy.sh
**/*.sh
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.sh: Always quote paths to handle spaces and special characters; avoid unguarded globbing
Keepset -eactive in shell scripts; ensure non-critical failures are guarded withcommand || true
**/*.sh: Use shebang#!/usr/bin/env bash(not/bin/bashor/bin/sh) for all Bash scripts
Use snake_case naming for functions in Bash scripts
Use snake_case for local variables and UPPER_CASE for constants/environment variables in Bash scripts
Use 2-space indentation in Bash scripts (no tabs)
Always quote variables and paths in Bash scripts to prevent word splitting
Check return codes in Bash scripts using|| exit 1or|| return 1for error handling
Uselocalkeyword for function-scoped variables in Bash scripts
Target Bash 3.2+ for compatibility with older systems like older macOS versions
Useset -efor error handling in Bash scripts to ensure failures are caught
Include fallback code for different Git versions (Git 2.5-2.21 compatibility fallbacks for modern Git 2.22+ commands)
Files:
lib/core.shlib/copy.sh
**/*.{bash,fish,sh}
📄 CodeRabbit inference engine (.github/instructions/sh.instructions.md)
**/*.{bash,fish,sh}: Bash 3.2+ compatible (macOS default), but 4.0+ features allowed where appropriate
Always quote variables: use"$var"not$var
Use function-scoped variables:local var="value"
Check return codes; functions return 1 on failure
Usesnake_casefor functions and variables,UPPER_CASEfor constants
Prefer[ ]over[[ ]]for POSIX portability; use[[only when needed
Always quote glob inputs; disable unintended globbing withset -ftemporarily if required
Avoid associative arrays in shell scripts; use simple string/loop constructs for Bash 3.2+ compatibility
Avoidreadarrayand process substitution unsupported in older Bash
Debug withbash -x ./bin/gtr <cmd>or wrap suspicious blocks withset -x/set +x
Check function presence withdeclare -f create_worktreeordeclare -f resolve_target
Use stderr for variable inspection:echo "DEBUG var=$var" >&2to keep stdout clean for command substitution
Keep dependencies minimal: only usegit,sed,awk,find,grep; avoid jq/curl unless justified
Check availability of external commands before use when adding new tools
Use"${var}"for variable expansion; for line loops usewhile IFS= read -r line; do ... doneto preserve spaces
Sanitize branch names viasanitize_branch_namefunction; do NOT duplicate logic elsewhere
Everything is sourced at startup withset -eenabled; functions call each other directly; no subshells except for hooks and AI tools
Files:
lib/core.shlib/copy.shcompletions/gtr.fishcompletions/gtr.bash
{bin/gtr,lib/**/*.sh,adapters/**/*.sh}
📄 CodeRabbit inference engine (.github/instructions/testing.instructions.md)
{bin/gtr,lib/**/*.sh,adapters/**/*.sh}: All commands must exit 0 (except intentional failures) and produce expected side-effects
No unquoted path errors; spaces must be handled in file paths
Hooks must run only once per creation/removal event
Files:
lib/core.shlib/copy.shbin/gtr
bin/gtr
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
bin/gtr: Dispatch commands throughcmd_*functions inbin/gtr(case block lines 36‑77)
UpdateGTR_VERSIONon line 8 ofbin/gtrwhen releasing; this affectsgtr version/--versionoutputGlobal
set -einbin/gtr: guard non-critical commands with|| true
list --porcelainoutput must remain stable for scripting purposesVersion number in
bin/gtr(line 8) must be updated when releasing a new version
Files:
bin/gtr
completions/*
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Shell completion files must be updated for bash, zsh, and fish when commands or adapters are added
Files:
completions/gtr.fishcompletions/gtr.bashcompletions/_git-gtr
completions/{gtr.bash,_git-gtr,gtr.fish}
📄 CodeRabbit inference engine (.github/instructions/completions.instructions.md)
completions/{gtr.bash,_git-gtr,gtr.fish}: Always update all three completion files (gtr.bash, _git-gtr, gtr.fish) when adding new commands, flags, editors, or AI adapters
Implement command completion in all three completion files to support top-level commands (new, rm, editor, ai, list, etc.) with appropriate tab-completion
Implement flag completion in all three completion files to support command-specific flags (e.g., --from, --force, --editor) with appropriate tab-completion
Implement adapter name completion in all three completion files, listing available editor names (cursor, vscode, zed) and AI tool names (aider, claude, codex) for --editor and --ai flags
Files:
completions/gtr.fishcompletions/gtr.bashcompletions/_git-gtr
completions/gtr.fish
📄 CodeRabbit inference engine (.github/instructions/completions.instructions.md)
completions/gtr.fish: In completions/gtr.fish, use custom predicates (__fish_git_gtr_needs_command, __fish_git_gtr_using_command) to handle git subcommand context and detect 'git gtr' usage
In completions/gtr.fish, support dynamic branch completion using 'git branch --format='%(refname:short)' and include special ID '1' for main repo
Files:
completions/gtr.fish
completions/**
📄 CodeRabbit inference engine (CLAUDE.md)
Update all three shell completion files when adding new commands or flags:
completions/gtr.bash,completions/_git-gtr(Zsh), andcompletions/gtr.fish(Fish)
Files:
completions/gtr.fishcompletions/gtr.bashcompletions/_git-gtr
completions/gtr.bash
📄 CodeRabbit inference engine (.github/instructions/completions.instructions.md)
completions/gtr.bash: In completions/gtr.bash, implement command completion using COMPREPLY array and compgen filtering for the current word ($cur)
In completions/gtr.bash, support dynamic branch completion using 'git branch --format='%(refname:short)' and include special ID '1' for main repo
Files:
completions/gtr.bash
completions/_git-gtr
📄 CodeRabbit inference engine (.github/instructions/completions.instructions.md)
completions/_git-gtr: In completions/_git-gtr, use Zsh completion framework with _arguments and _describe/_values for sophisticated completion logic with descriptions and grouping
In completions/_git-gtr, support dynamic branch completion using 'git branch --format='%(refname:short)' and include special ID '1' for main repo
Files:
completions/_git-gtr
🪛 Shellcheck (0.11.0)
completions/gtr.bash
[warning] 25-25: Prefer mapfile or read -a to split command output (or quote to avoid splitting).
(SC2207)
[warning] 50-50: Prefer mapfile or read -a to split command output (or quote to avoid splitting).
(SC2207)
[warning] 56-56: Prefer mapfile or read -a to split command output (or quote to avoid splitting).
(SC2207)
🔇 Additional comments (4)
completions/gtr.bash (1)
25-25: Copy completions and config keys look consistentThe new
copysubcommand is correctly wired into bash completion:
- Top‑level command list now includes
copy.copy)case offers-n/--dry-run,-a/--all, and--fromwhen completing flags, and1+ branch names otherwise.configkey completion includes the newgtr.copy.*keys, matching the help text and config usage.No issues from the ShellCheck SC2207 hints here; the existing
COMPREPLY=($(compgen ...))pattern is standard for bash completion in this project.Also applies to: 48-58, 68-72
completions/gtr.fish (1)
38-48: Fish completion forcopymatches CLI behavior
copyis added to the top‑level command list with an appropriate description.- Short/long flags for the copy command (
-n/--dry-run,-a/--all,--from) are exposed with clear descriptions.- Branch completion for
copyreuses__gtr_worktree_branches, giving1plus local branches, consistent with other commands.gtr.copy.*config keys are present in the config completion block.Looks good and aligned with the other shells.
Also applies to: 65-69, 86-92, 95-99
lib/copy.sh (1)
19-24: Dry‑run support incopy_patternsis backward‑compatible and side‑effect free
- The extra
[dry_run]parameter is optional and defaults to"false", so existing callers (likecmd_create) retain their behavior.- When
dry_runis"true", the function:
- Skips
mkdir -pandcpentirely.- Logs
[dry-run] Would copy: <file>per match and a final[dry-run] Would copy N file(s)summary.- Real copies still create parent directories and log per‑file success/failure, with the same counting and overall summary as before.
- All new logic keeps paths quoted and respects the existing safety checks on patterns.
This is a clean extension and fits the new
cmd_copyusage well.Also applies to: 30-31, 106-123, 164-181, 192-197
completions/_git-gtr (1)
18-34: Zsh completion forcopyis wired correctly
copyis added to the subcommand list with a clear description.- First positional argument after
copynow completes to1plus branch names, matching other branch‑oriented commands (go,run,rm).- Subsequent arguments for
copyuse_argumentsto expose:
-n/--dry-run,-a/--all, and--from(with worktree‑aware completion),- Positional targets completed from the same branch/
1set.This matches the new CLI and stays consistent with the existing Zsh completion style.
Also applies to: 63-71, 97-107
Pull Request
Description
Motivation
Fixes # (issue)
Type of Change
Testing
Manual Testing Checklist
Tested on:
Core functionality tested:
git gtr new <branch>- Create worktreegit gtr go <branch>- Navigate to worktreegit gtr editor <branch>- Open in editor (if applicable)git gtr ai <branch>- Start AI tool (if applicable)git gtr rm <branch>- Remove worktreegit gtr list- List worktreesgit gtr config- Configuration commands (if applicable)Test Steps
Expected behavior:
Actual behavior:
Breaking Changes
Checklist
Before submitting this PR, please check:
git gtr(production) and./bin/gtr(development)Additional Context
License Acknowledgment
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache License 2.0.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.