fix: repair worktree starts from origin/<default-branch>

When repairing a stale polecat worktree, start from origin/<default-branch>
instead of the bare repo's HEAD. This ensures repaired polecats have the
latest fetched commits rather than potentially stale code.

- Add WorktreeAddFromRef to git package for creating worktrees from a ref
- RepairWorktreeWithOptions now uses origin/<default-branch> as start point
- Respects rig's configured default branch (main, master, etc.)

Based on PR #112 by markov-kernel. Test changes from that PR can be
submitted separately.

Closes #101

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: markov-kernel <markov-kernel@users.noreply.github.com>
This commit is contained in:
gastown/crew/george
2026-01-04 14:46:19 -08:00
committed by Steve Yegge
parent af95b7b7f4
commit bef5a10250
2 changed files with 18 additions and 3 deletions

View File

@@ -523,6 +523,13 @@ func (g *Git) WorktreeAdd(path, branch string) error {
return err return err
} }
// WorktreeAddFromRef creates a new worktree at the given path with a new branch
// starting from the specified ref (e.g., "origin/main").
func (g *Git) WorktreeAddFromRef(path, branch, startPoint string) error {
_, err := g.run("worktree", "add", "-b", branch, path, startPoint)
return err
}
// WorktreeAddDetached creates a new worktree at the given path with a detached HEAD. // WorktreeAddDetached creates a new worktree at the given path with a detached HEAD.
func (g *Git) WorktreeAddDetached(path, ref string) error { func (g *Git) WorktreeAddDetached(path, ref string) error {
_, err := g.run("worktree", "add", "--detach", path, ref) _, err := g.run("worktree", "add", "--detach", path, ref)

View File

@@ -446,13 +446,21 @@ func (m *Manager) RepairWorktreeWithOptions(name string, force bool, opts AddOpt
// Fetch latest from origin to ensure we have fresh commits (non-fatal: may be offline) // Fetch latest from origin to ensure we have fresh commits (non-fatal: may be offline)
_ = repoGit.Fetch("origin") _ = repoGit.Fetch("origin")
// Create fresh worktree with unique branch name // Determine the start point for the new worktree
// Use origin/<default-branch> to ensure we start from latest fetched commits
defaultBranch := "main"
if rigCfg, err := rig.LoadRigConfig(m.rig.Path); err == nil && rigCfg.DefaultBranch != "" {
defaultBranch = rigCfg.DefaultBranch
}
startPoint := fmt.Sprintf("origin/%s", defaultBranch)
// Create fresh worktree with unique branch name, starting from origin's default branch
// Old branches are left behind - they're ephemeral (never pushed to origin) // Old branches are left behind - they're ephemeral (never pushed to origin)
// and will be cleaned up by garbage collection // and will be cleaned up by garbage collection
// Use base36 encoding for shorter branch names (8 chars vs 13 digits) // Use base36 encoding for shorter branch names (8 chars vs 13 digits)
branchName := fmt.Sprintf("polecat/%s-%s", name, strconv.FormatInt(time.Now().UnixMilli(), 36)) branchName := fmt.Sprintf("polecat/%s-%s", name, strconv.FormatInt(time.Now().UnixMilli(), 36))
if err := repoGit.WorktreeAdd(polecatPath, branchName); err != nil { if err := repoGit.WorktreeAddFromRef(polecatPath, branchName, startPoint); err != nil {
return nil, fmt.Errorf("creating fresh worktree: %w", err) return nil, fmt.Errorf("creating fresh worktree from %s: %w", startPoint, err)
} }
// NOTE: We intentionally do NOT write to CLAUDE.md here. // NOTE: We intentionally do NOT write to CLAUDE.md here.