fix(worktree): add -f flag to handle missing but registered state (#609)

Problem:
When the daemon auto-sync runs with --auto-commit --auto-push, the sync
branch pull operation consistently fails with:

  fatal: '.git/beads-worktrees/beads-metadata' is a missing but already
  registered worktree; use 'add -f' to override, or 'prune' or 'remove'
  to clear

This occurs because:
1. Daemon creates worktree at .git/beads-worktrees/<branch>
2. Git registers it in .git/worktrees/<branch>
3. After the operation, worktree contents are removed
4. Git registration persists, pointing to the now-empty path
5. Subsequent CreateBeadsWorktree calls fail because os.Stat() returns
   error (path missing), so no cleanup happens, then git worktree add
   fails because git still has it registered

Root cause:
The git worktree add commands in CreateBeadsWorktree() did not use the
-f (force) flag, which is needed to override the "missing but already
registered" state.

Solution:
Add -f flag to both git worktree add commands (for existing branch and
new branch cases). Per git documentation, -f overrides the safeguard
that prevents creating a worktree when the path is already registered
but missing.

The existing git worktree prune call (line 30-32) was intended to handle
this, but it runs before the path check and may not always clear the
registration in time. The -f flag provides a robust fallback.

Testing:
- All existing worktree tests pass
- Added regression test TestCreateBeadsWorktree_MissingButRegistered
  that simulates the exact issue #609 scenario

Fixes #609

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
This commit is contained in:
Charles P. Cross
2025-12-18 23:29:32 -05:00
committed by GitHub
parent 99e261c643
commit 2b031b9441
2 changed files with 66 additions and 2 deletions

View File

@@ -52,13 +52,15 @@ func (wm *WorktreeManager) CreateBeadsWorktree(branch, worktreePath string) erro
branchExists := wm.branchExists(branch)
// Create worktree without checking out files initially
// Use -f (force) to handle "missing but already registered" state (issue #609)
// This occurs when the worktree directory was deleted but git registration persists
var cmd *exec.Cmd
if branchExists {
// Checkout existing branch
cmd = exec.Command("git", "worktree", "add", "--no-checkout", worktreePath, branch)
cmd = exec.Command("git", "worktree", "add", "-f", "--no-checkout", worktreePath, branch)
} else {
// Create new branch
cmd = exec.Command("git", "worktree", "add", "--no-checkout", "-b", branch, worktreePath)
cmd = exec.Command("git", "worktree", "add", "-f", "--no-checkout", "-b", branch, worktreePath)
}
cmd.Dir = wm.repoPath