gastownhall/beads · error

target common git directory changed

Error message

target common git directory changed

What it means

Revalidation also compares the target's common git directory with the plan's recorded commonDir. A mismatch means the worktree now shares metadata with a different repository (or the repo's common dir moved), so executing the prepared plan could damage the wrong repository. bd aborts, marking CommonDirectory as Changed, and reports this error.

Source

Thrown at cmd/bd/worktree_cmd.go:1418

		}
		return worktreeRevalidationObservation{facts: facts, err: fmt.Errorf("registered target identity changed")}
	}
	facts.Registration = worktreeremove.InvariantStable
	facts.LockPrune = worktreeremove.InvariantStable
	facts.TargetPath = worktreeremove.InvariantStable

	currentTarget, err := inspectWorktreeTarget(ctx, plan.git, currentEntry)
	if err != nil {
		return worktreeRevalidationObservation{facts: facts, err: err}
	}
	if !sameWorktreePath(currentTarget.gitDir, plan.target.gitDir) {
		facts.GitAdminDirectory = worktreeremove.InvariantChanged
		return worktreeRevalidationObservation{facts: facts, err: fmt.Errorf("target git directory changed")}
	}
	facts.GitAdminDirectory = worktreeremove.InvariantStable
	if !sameWorktreePath(currentTarget.commonDir, plan.commonDir) {
		facts.CommonDirectory = worktreeremove.InvariantChanged
		return worktreeRevalidationObservation{facts: facts, err: fmt.Errorf("target common git directory changed")}
	}
	facts.CommonDirectory = worktreeremove.InvariantStable
	if currentTarget.headOID != plan.target.headOID {
		facts.Head = worktreeremove.InvariantChanged
		return worktreeRevalidationObservation{facts: facts, err: fmt.Errorf("target HEAD changed from %s to %s", plan.target.headOID, currentTarget.headOID)}
	}
	facts.Head = worktreeremove.InvariantStable
	if currentTarget.status != plan.target.status {
		if (currentTarget.status == "") != (plan.target.status == "") {
			facts.Cleanliness = worktreeremove.InvariantChanged
		} else {
			facts.Cleanliness = worktreeremove.InvariantStable
		}
		facts.StatusBytes = worktreeremove.InvariantChanged
		return worktreeRevalidationObservation{facts: facts, err: fmt.Errorf("target cleanliness changed")}
	}
	facts.Cleanliness = worktreeremove.InvariantStable
	facts.StatusBytes = worktreeremove.InvariantStable

View on GitHub (pinned to 71377f2769)

Solutions

  1. Rebuild by re-running `bd worktree remove` so the plan captures the current common dir
  2. Verify the main repo path hasn't moved; update the worktree with `git worktree repair` from the primary repo if it has
  3. Serialize operations: don't move/re-clone the repository while a worktree removal is pending

Example fix

// before: repo moved after plan was built
$ bd worktree remove feature
// error: target common git directory changed
// after
$ cd /new/location/repo && git worktree repair
$ bd worktree remove feature   # fresh plan
Defensive patterns

Strategy: retry

Validate before calling

cur=$(git -C /wt/feature rev-parse --path-format=absolute --git-common-dir)
[ "$cur" = "$RECORDED_COMMON_DIR" ] || { echo 'repo common dir moved; rebuild plan'; exit 1; }

Type guard

func commonDirStable(before, after string) bool {
	return filepath.Clean(before) == filepath.Clean(after)
}

Try / catch

obs := revalidateWorktreePlan(ctx, plan)
if obs.err != nil && strings.Contains(obs.err.Error(), "common git directory changed") {
	return fmt.Errorf("repository structure changed; re-run bd worktree remove from the primary repo")
}

Prevention

When it happens

Trigger: Executing a removal plan after the repository's common dir changed (repo moved/cloned, .git structure rearranged, worktree re-linked to another clone) between plan build and execution.

Common situations: The main repo was moved or its path changed (macOS /Volumes mounts, renamed directories) after the plan was built; the worktree was re-added against a different clone; `git worktree repair` relinked to a different primary.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/4dd21fae62fd0bce. Report an issue: GitHub.