Skip to content

fix(worktree): reuse an existing worktree found on disk, not just via cwd - #414

Merged
getappz merged 2 commits into
masterfrom
fix-worktree-reuse-from-repo-root
Aug 9, 2026
Merged

fix(worktree): reuse an existing worktree found on disk, not just via cwd#414
getappz merged 2 commits into
masterfrom
fix-worktree-reuse-from-repo-root

Conversation

@getappz

@getappz getappz commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Summary

already_isolated_for(branch, repo_root) only recognizes a re-claim when the calling process is itself already running from inside that worktree (compares --git-dir vs --git-common-dir on repo_root). The daemon's normal dispatch always calls create_worktree from the main repo root, so this check never fires there — even when .worktrees/task/N already exists on disk as a valid worktree for the branch. create_worktree then falls through to git worktree add, which refuses to re-add an already-checked-out branch, surfacing as "claim succeeded but no worktree was created (bad git state?)" on every redispatch of an item whose worktree survived a prior claim attempt.

Root-caused while dogfooding item #43's autonomous redispatch (repeatedly hit this exact failure); very likely the real cause behind item #30's "database is locked" report too, not a two-item concurrency collision as originally guessed there.

worktree_already_checked_out(worktree_path, branch) adds the on-disk counterpart to already_isolated_for: does a worktree already exist at this path, checked out to this branch, regardless of which process is asking. Reuses the same branch --show-current check already_isolated_for already does internally.

Test plan

  • New test create_worktree_reuses_an_existing_worktree_when_called_from_the_repo_root — reproduces the daemon's exact calling pattern (two create_worktree calls from the repo root, never from inside the worktree); confirmed it fails first with fatal: '.../.worktrees/task/1' already exists, then passes after the fix
  • cargo test -p flare-git-core worktree:: — 23 passed, 0 failed
  • cargo build --workspace clean
  • cargo clippy -p flare-git-core --all-targets — no new warnings
  • cargo fmt --check clean

Summary by CodeRabbit

  • Bug Fixes
    • Improved worktree handling when creating a worktree from the repository root.
    • Existing worktrees are now detected and reused instead of being added again.
    • Repeated worktree creation requests now complete successfully without creating duplicate worktrees or failing unexpectedly.
    • This provides more reliable behavior when reopening or reclaiming an already configured worktree.

… cwd

already_isolated_for(branch, repo_root) only recognizes a re-claim when the
calling process is itself already running from inside that worktree
(compares --git-dir vs --git-common-dir on repo_root). The daemon's normal
dispatch always calls create_worktree from the main repo root, so this check
never fires there, even when .worktrees/task/N already exists on disk as a
valid worktree for the branch. create_worktree then falls through to `git
worktree add`, which refuses to re-add an already-checked-out branch,
surfacing as "claim succeeded but no worktree was created (bad git state?)"
on every redispatch of an item whose worktree survived a prior claim.

worktree_already_checked_out(worktree_path, branch) adds the on-disk
counterpart: does a worktree already exist at this path, checked out to this
branch, regardless of which process is asking. Reuses the same
branch --show-current check already_isolated_for uses internally.

Agentflare-Agent: claude-code
Agentflare-Branch: fix-worktree-reuse-from-repo-root
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: af97b5f5-271e-446d-9618-3d0092a245f2

📥 Commits

Reviewing files that changed from the base of the PR and between 21b38b1 and 0b02720.

📒 Files selected for processing (1)
  • crates/flare-git-core/src/worktree.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/flare-git-core/src/worktree.rs

📝 Walkthrough

Walkthrough

create_worktree now detects an existing worktree checked out to the requested branch and reuses it. A regression test covers repeated creation calls from the repository root.

Changes

Worktree reuse

Layer / File(s) Summary
Detect and test existing worktree reuse
crates/flare-git-core/src/worktree.rs
The flow checks whether an existing directory uses the requested branch. Matching worktrees are reused, and regression coverage verifies repeated creation calls.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: reusing an existing on-disk worktree.
Description check ✅ Passed The description explains the change, root cause, regression test, and completed validation; only the optional reviewer notes section is absent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-worktree-reuse-from-repo-root

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@crates/flare-git-core/src/worktree.rs`:
- Around line 69-83: Update worktree_already_checked_out to validate ownership
using git worktree list --porcelain executed from repo_root, matching both the
canonical worktree_path and branch before returning true; do not rely solely on
git branch --show-current. Adjust callers and related symbols as needed to
provide repo_root, and add a negative test covering an unrelated repository at
the target path.
🪄 Autofix

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: Pro

Run ID: 86540761-f40d-48f9-b503-b1625fc4573f

📥 Commits

Reviewing files that changed from the base of the PR and between 3b593ab and 21b38b1.

📒 Files selected for processing (1)
  • crates/flare-git-core/src/worktree.rs

Comment on lines +69 to +83
/// `true` if `worktree_path` already exists on disk and is itself a git
/// worktree checked out to `branch` -- the on-disk counterpart to
/// `already_isolated_for` above, for callers running from outside the
/// worktree (the daemon's normal case) rather than from inside it.
#[must_use]
fn worktree_already_checked_out(worktree_path: &Path, branch: &str) -> bool {
if !worktree_path.is_dir() {
return false;
}
match run_git_in(worktree_path, &["branch", "--show-current"]) {
Ok(b) => b == branch,
Err(_) => false,
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT

git -C "$tmp" init -q
git -C "$tmp" config user.email test@example.com
git -C "$tmp" config user.name Test
printf root > "$tmp/root.txt"
git -C "$tmp" add root.txt
git -C "$tmp" commit -qm init

candidate="$tmp/.worktrees/task/1"
mkdir -p "$candidate"
git -C "$candidate" init -q
git -C "$candidate" config user.email test@example.com
git -C "$candidate" config user.name Test
printf nested > "$candidate/nested.txt"
git -C "$candidate" add nested.txt
git -C "$candidate" commit -qm init
git -C "$candidate" branch -M task/1

test "$(git -C "$candidate" branch --show-current)" = "task/1"
! git -C "$tmp" worktree list --porcelain | grep -Fq "$candidate"

Repository: getappz/agentflare

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- helper and caller ---'
sed -n '1,110p' crates/flare-git-core/src/worktree.rs
sed -n '220,270p' crates/flare-git-core/src/worktree.rs
printf '%s\n' '--- run_git_in and ownership-related calls ---'
rg -n -C 4 'fn run_git_in|worktree_already_checked_out|worktree list|worktree add|already_isolated_for' crates/flare-git-core/src/worktree.rs

Repository: getappz/agentflare

Length of output: 11950


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- shell module ---'
fd -i -t f 'shell' .
rg -n -C 8 'pub fn run_in|fn run_in|run_in_ok' crates
printf '%s\n' '--- relevant tests ---'
sed -n '1035,1140p' crates/flare-git-core/src/worktree.rs

Repository: getappz/agentflare

Length of output: 30758


Validate worktree ownership before reusing the path.

git branch --show-current only proves that Git reports the requested branch from worktree_path. It does not prove that worktree_path is registered under repo_root. An unrelated repository at that path can cause the caller to skip worktree creation and modify the wrong checkout.

Match the path and branch against git worktree list --porcelain from repo_root. Add a negative test for an unrelated repository at the target path.

🤖 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 `@crates/flare-git-core/src/worktree.rs` around lines 69 - 83, Update
worktree_already_checked_out to validate ownership using git worktree list
--porcelain executed from repo_root, matching both the canonical worktree_path
and branch before returning true; do not rely solely on git branch
--show-current. Adjust callers and related symbols as needed to provide
repo_root, and add a negative test covering an unrelated repository at the
target path.

@getappz
getappz merged commit cba5bc3 into master Aug 9, 2026
17 checks passed
@getappz
getappz deleted the fix-worktree-reuse-from-repo-root branch August 9, 2026 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant