feat: inherit sparse-checkout in new worktrees#186
Conversation
When creating a new worktree from one with sparse-checkout enabled, the new worktree inherits the cone pattern automatically. Controlled by gtr.sparse.inherit config (default on) and --sparse/--no-sparse flags. Adds reusable helpers for sparse-checkout replication.
WalkthroughAdds sparse-checkout inheritance to ChangesSparse-Checkout Inheritance
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant cmd_create
participant WorktreeHelpers
participant Git
User->>cmd_create: git gtr new --sparse or --no-sparse
cmd_create->>WorktreeHelpers: resolve sparse source and capability
WorktreeHelpers-->>cmd_create: source and checkout mode
cmd_create->>Git: create worktree with sparse context
Git-->>cmd_create: created worktree
cmd_create->>Git: validate sparse state or force full checkout
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
tests/sparse.bats (2)
116-154: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExercise sparse config/flag precedence explicitly.
The command tests cover the default-on path and
--no-sparse, but they never assertgtr.sparse.inherit=falseor--sparseoverriding that config. That leaves the precedence block inlib/commands/create.shonly partially covered, even though the feature contract depends on it.Suggested test additions
+@test "cmd_create honors gtr.sparse.inherit=false" { + source_gtr_commands + make_sparse_worktree "$TEST_WORKTREES_DIR/base" base apps/web + git -C "$TEST_REPO" config gtr.sparse.inherit false + + run cmd_create feat-config-off --from base --yes --no-fetch --no-hooks --no-copy + [ "$status" -eq 0 ] + + wt="$TEST_WORKTREES_DIR/feat-config-off" + [ -d "$wt/apps/api" ] + [ "$(git -C "$wt" config --bool core.sparseCheckout 2>/dev/null || echo false)" != "true" ] +} + +@test "cmd_create --sparse overrides gtr.sparse.inherit=false" { + source_gtr_commands + make_sparse_worktree "$TEST_WORKTREES_DIR/base" base apps/web + git -C "$TEST_REPO" config gtr.sparse.inherit false + + run cmd_create feat-config-override --from base --sparse --yes --no-fetch --no-hooks --no-copy + [ "$status" -eq 0 ] + + wt="$TEST_WORKTREES_DIR/feat-config-override" + [ "$(git -C "$wt" config --bool core.sparseCheckout)" = "true" ] + [ -d "$wt/apps/web" ] + [ ! -d "$wt/apps/api" ] +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/sparse.bats` around lines 116 - 154, Add tests in sparse.bats to cover sparse precedence in cmd_create: explicitly verify that gtr.sparse.inherit=false prevents sparse-checkout inheritance from a sparse --from worktree, and that --sparse overrides that config to keep sparse checkout enabled. Reuse the existing cmd_create, make_sparse_worktree, and git -C "$wt" config assertions so the new cases exercise the precedence logic in lib/commands/create.sh alongside the current default-on and --no-sparse coverage.
93-114: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a non-cone inheritance test.
This only exercises the
core.sparseCheckoutCone=truebranch.apply_inherited_sparse()has a separate non-cone path that initializes sparse-checkout without--coneand pipes raw patterns throughset --stdin, so a regression there would currently ship untested.Suggested test shape
+@test "apply_inherited_sparse replicates non-cone patterns into a new worktree" { + git -C "$TEST_REPO" worktree add --quiet -b base-noncone "$TEST_WORKTREES_DIR/base-noncone" HEAD + git -C "$TEST_WORKTREES_DIR/base-noncone" sparse-checkout init --no-cone >/dev/null + printf 'apps/web/*\n!apps/web/file.txt\npackages/*\n' \ + | git -C "$TEST_WORKTREES_DIR/base-noncone" sparse-checkout set --stdin >/dev/null + git -C "$TEST_REPO" worktree add --no-checkout --quiet -b feat-noncone "$TEST_WORKTREES_DIR/feat-noncone" base-noncone + + run apply_inherited_sparse "$TEST_WORKTREES_DIR/feat-noncone" "$TEST_WORKTREES_DIR/base-noncone" + [ "$status" -eq 0 ] + [ "$(git -C "$TEST_WORKTREES_DIR/feat-noncone" config --bool core.sparseCheckout)" = "true" ] + [ "$(git -C "$TEST_WORKTREES_DIR/feat-noncone" config --bool core.sparseCheckoutCone 2>/dev/null || echo false)" != "true" ] + [ "$(git -C "$TEST_WORKTREES_DIR/base-noncone" sparse-checkout list)" = "$(git -C "$TEST_WORKTREES_DIR/feat-noncone" sparse-checkout list)" ] +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/sparse.bats` around lines 93 - 114, Add a test that covers the non-cone inheritance path in apply_inherited_sparse, since the current sparse.bats case only verifies core.sparseCheckoutCone=true. Create a fixture where the source worktree uses non-cone sparse-checkout patterns, then assert the inherited worktree preserves core.sparseCheckout=true, keeps core.sparseCheckoutCone false, and applies the raw patterns via sparse-checkout set --stdin behavior rather than cone directories. Use apply_inherited_sparse, make_sparse_worktree, and sparse-checkout list to locate and validate the non-cone branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/commands/create.sh`:
- Around line 200-206: The sparse-checkout inheritance failure is being
downgraded to a warning in the create_worktree flow, which can incorrectly
continue after create_worktree with no_checkout set and leave a partially
initialized worktree. Update the create.sh logic around apply_inherited_sparse
so that a failure is treated as a hard error (or otherwise triggers a proper
fallback) before the copy/hooks/success path continues, and make sure the
behavior is enforced in the create_worktree/no_checkout branch rather than only
logging through log_warn.
In `@lib/core.sh`:
- Around line 622-630: The worktree selection in the sparse-checkout helper
currently stops at the first matching ref even when that worktree is not
sparse-enabled, causing the fallback path to be skipped. Update the logic in the
helper that uses _worktree_path_for_ref and the core.sparseCheckout check so it
only accepts a matching worktree when sparse checkout is true; otherwise
continue falling back to the current repo/top-level worktree instead of
returning empty. Keep the existing behavior for enabled sparse worktrees, but
ensure non-sparse matches do not short-circuit the search.
- Around line 593-603: The branch matching in the worktree lookup is stripping
too much from remote refs, causing slash-separated names like feature/user-auth
to lose their prefix and fail to match. Update the normalization logic in the
worktree scan around the ref_short/branch comparison so it preserves the branch
path after the remote name instead of using only the last path segment, and keep
the comparison in the same block that reads worktree and branch entries.
- Around line 640-676: The apply_inherited_sparse function currently assumes git
sparse-checkout init/list/set --stdin are available, but that only works on Git
2.25+, so older supported clients can leave the new worktree unmaterialized. Add
a Git version guard in apply_inherited_sparse and, when the src_wt/new_wt
commands are unsupported, either skip sparse inheritance entirely or fall back
to a normal checkout so the new worktree is fully populated. Keep the existing
log_warn paths for real failures, and use the apply_inherited_sparse flow to
locate the compatibility branch.
---
Nitpick comments:
In `@tests/sparse.bats`:
- Around line 116-154: Add tests in sparse.bats to cover sparse precedence in
cmd_create: explicitly verify that gtr.sparse.inherit=false prevents
sparse-checkout inheritance from a sparse --from worktree, and that --sparse
overrides that config to keep sparse checkout enabled. Reuse the existing
cmd_create, make_sparse_worktree, and git -C "$wt" config assertions so the new
cases exercise the precedence logic in lib/commands/create.sh alongside the
current default-on and --no-sparse coverage.
- Around line 93-114: Add a test that covers the non-cone inheritance path in
apply_inherited_sparse, since the current sparse.bats case only verifies
core.sparseCheckoutCone=true. Create a fixture where the source worktree uses
non-cone sparse-checkout patterns, then assert the inherited worktree preserves
core.sparseCheckout=true, keeps core.sparseCheckoutCone false, and applies the
raw patterns via sparse-checkout set --stdin behavior rather than cone
directories. Use apply_inherited_sparse, make_sparse_worktree, and
sparse-checkout list to locate and validate the non-cone branch.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 2aeb9dfc-e4e0-4bd2-8819-9bf9289313c3
📒 Files selected for processing (13)
README.mdcompletions/_git-gtrcompletions/git-gtr.fishcompletions/gtr.bashdocs/advanced-usage.mddocs/configuration.mdlib/commands/create.shlib/commands/help.shlib/config.shlib/core.shscripts/generate-completions.shtemplates/.gtrconfig.exampletests/sparse.bats
…heritance - Preserve slash-separated branch paths in _worktree_path_for_ref - Allow fallback to top-level worktree when matching worktree is not sparse - Add Git 2.25+ guard for sparse-checkout support with full checkout fallback - Fix non-cone mode to use init --no-cone (git defaults to cone mode) - Improve error handling: failed sparse inheritance now falls back to full checkout and hard-errors if that fails, instead of leaving --no-checkout worktree empty - Add tests for slash refs, non-cone inheritance, and sparse config precedence
|
from my agent: Here's what I fixed against each finding: core.sh
create.sh
tests/sparse.bats
All nitpicks were valid and addressed (the non-cone test caught a genuine latent bug, so no skips were warranted). |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/config.sh`:
- Around line 223-242: Update cfg_bool’s source-selection loop to skip the
worktree case when the installed Git lacks --worktree support (Git versions
older than 2.20), using the repository’s existing Git version or
capability-checking helpers if available. Ensure unsupported worktree options do
not cause an early return, allowing local, file, global, and system sources to
be checked normally.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: d4565dcf-380b-43de-8847-88324c828361
📒 Files selected for processing (13)
README.mdcompletions/_git-gtrcompletions/git-gtr.fishdocs/advanced-usage.mddocs/configuration.mdlib/commands/create.shlib/commands/help.shlib/config.shlib/core.shscripts/generate-completions.shtemplates/.gtrconfig.exampletests/config.batstests/sparse.bats
✅ Files skipped from review due to trivial changes (5)
- templates/.gtrconfig.example
- lib/commands/help.sh
- docs/advanced-usage.md
- README.md
- docs/configuration.md
🚧 Files skipped from review as they are similar to previous changes (5)
- completions/_git-gtr
- completions/git-gtr.fish
- scripts/generate-completions.sh
- lib/commands/create.sh
- lib/core.sh
Summary
New worktrees can inherit sparse-checkout settings from the worktree that supplies their base ref. This keeps large monorepo worktrees narrow without materializing the full tree first.
gtr.sparse.inheritcontrols inheritance and defaults totrue.--sparseand--no-sparseoverride the setting per command.git gtris run from a sparse worktree.Implementation
On Git 2.36+,
git gtr newresolves the worktree holding--from(falling back to the current worktree), then runs onlygit worktree addin that source context. Git natively copies its sparse patterns andconfig.worktreebefore checkout.Source selection is deterministic:
--fromnames a local branch, remote-tracking branch, tag, or non-symbolic commit-ish.Git 2.17–2.35 retains the existing full-checkout behavior. An explicit
--sparserequest prints a Git 2.36+ requirement warning.User experience
Validation
No new external dependencies are introduced.
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
gtr.sparse.inherit).git gtr new --sparse/--no-sparseto override sparse behavior per command.git gtr configboolean handling forgtr.sparse.inherit.