Skip to content

copy: ** glob patterns don't match root-level files on macOS (Bash 3.2 find fallback) #132

Description

@okazuki58

Description

When using ** glob patterns in gtr.copy.include config, root-level files are not copied on macOS (which uses Bash 3.2 by default).

Steps to Reproduce

  1. macOS with default Bash 3.2
  2. .gtrconfig:
    [copy]
    include = **/.env*
    include = **/CLAUDE.md
  3. Root-level .env and CLAUDE.md exist in the main repo
  4. Run git gtr copy <worktree-name>

Expected

Root-level .env and CLAUDE.md are copied to the worktree.

Actual

==> Copying to: <branch-name>
[!] Failed to copy
[!] Failed to copy

With --dry-run:

==> [dry-run] Would copy to: <branch-name>
[OK] [dry-run] Would copy: 
[OK] [dry-run] Would copy: 
[OK] [dry-run] Would copy 2 file(s)

File names are empty in the output.

Root Cause

In lib/copy.sh, when Bash 3.2 doesn't support globstar, the code falls back to find:

$(find . -path "./$pattern" -type f 2>/dev/null)

For pattern **/.env*, this becomes find . -path "./**/.env*" -type f.

The problem is twofold:

  1. find -path doesn't treat ** as recursive glob — it's just a regular wildcard. The pattern **/.env* requires a directory separator before .env, so it never matches root-level files like ./.env.

  2. Empty results still trigger one loop iteration — when find returns nothing, the while read loop with heredoc executes once with an empty string, causing cp "" <dest> to fail.

Workaround

Use patterns without **/ prefix:

[copy]
include = .env*
include = CLAUDE.md

Suggested Fix

  1. For **-prefixed patterns, also match root-level files (e.g., convert **/.env* to find . -name ".env*" -type f)
  2. Add an empty-string guard in the copy loop: [ -z "$file" ] && continue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions