fix(mcp): don't warn "different git working tree" for submodules covered by the parent index (#1031, #1033) (#1039)
Indexing a super-repo now descends into its submodules and gitlinked clones, so a query run from inside one resolves up to the parent's unified index — whose graph DOES contain that nested repo's files. But the git-worktree-mismatch warning still fired, telling the agent the results were from "a different working tree" and to run `codegraph init -i` — which would split the submodule back into its own index and undo the unified view. A false positive carrying harmful advice. Distinguish a genuine borrowed worktree (the SAME repository on a different branch — shares a git common dir with the index root) from a submodule/embedded clone (a DIFFERENT repository — its own common dir), and suppress the warning only for the latter. Add gitCommonDir() for the check. The issue-#155 linked-worktree case is unchanged. Verified end-to-end: the warning no longer fires for a submodule-rooted MCP session and still fires for a real linked worktree. Edit-sync (manual sync + the live watcher) keeps the nested repo's files current on both macOS and Linux (active-submodule and bare-gitlink shapes), so suppressing the warning is safe. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
a4dfc3438f
commit
f73227d2f5
@@ -43,6 +43,30 @@ export function gitWorktreeRoot(dir: string): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute, symlink-resolved git **common** directory for `dir` — the shared
|
||||
* `.git` that all worktrees of one repository point at. Linked worktrees of the
|
||||
* same repo report the SAME common dir; a submodule or an embedded clone is a
|
||||
* DIFFERENT repository and reports its own (`…/.git/modules/<name>` or its own
|
||||
* `.git`). That distinction is what separates a genuine "borrowed worktree"
|
||||
* from a nested repo the parent index already covers. Null when not a repo.
|
||||
*/
|
||||
export function gitCommonDir(dir: string): string | null {
|
||||
try {
|
||||
const out = execFileSync('git', ['rev-parse', '--git-common-dir'], {
|
||||
cwd: dir,
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
windowsHide: true,
|
||||
}).trim();
|
||||
if (!out) return null;
|
||||
// `--git-common-dir` is relative to cwd unless already absolute.
|
||||
return realpath(path.isAbsolute(out) ? out : path.resolve(dir, out));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export interface WorktreeIndexMismatch {
|
||||
/** The git working tree the command was run from. */
|
||||
worktreeRoot: string;
|
||||
@@ -76,6 +100,20 @@ export function detectWorktreeIndexMismatch(
|
||||
// plain ancestor directory", and avoids warning outside git entirely.
|
||||
if (gitWorktreeRoot(resolvedIndexRoot) !== resolvedIndexRoot) return null;
|
||||
|
||||
// Don't flag a nested repo (submodule / embedded clone) that `indexRoot`'s
|
||||
// index ALREADY covers: indexing a super-repo descends into its submodules
|
||||
// and gitlinked clones, so a query run from inside one resolves up to the
|
||||
// parent index — whose graph *does* contain that nested repo's files. The
|
||||
// warning's premise ("results are a different branch; symbols changed only
|
||||
// here are missing") is false there, and its "run codegraph init -i" advice
|
||||
// would needlessly fragment the unified workspace index. A genuine borrowed
|
||||
// worktree and the index root are the SAME repository (they share a git
|
||||
// common dir); a submodule/embedded clone is a DIFFERENT repository and does
|
||||
// not — so suppress only when the two clearly differ. (#1031, #1033)
|
||||
const worktreeCommon = gitCommonDir(worktreeRoot);
|
||||
const indexCommon = gitCommonDir(resolvedIndexRoot);
|
||||
if (worktreeCommon && indexCommon && worktreeCommon !== indexCommon) return null;
|
||||
|
||||
return { worktreeRoot, indexRoot: resolvedIndexRoot };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user