diff --git a/.changeset/fix-staged-git-dir-worktree.md b/.changeset/fix-staged-git-dir-worktree.md new file mode 100644 index 000000000..ea2008731 --- /dev/null +++ b/.changeset/fix-staged-git-dir-worktree.md @@ -0,0 +1,5 @@ +--- +"react-doctor": patch +--- + +Fix `--staged` refusing to scan in linked git worktrees when `GIT_DIR` is set. Clear the inherited `GIT_DIR` environment variable in the staged divergence check so git status resolves paths correctly, matching the fix for scoped scans in #1516. diff --git a/packages/react-doctor/src/cli/utils/git-hook-shared.ts b/packages/react-doctor/src/cli/utils/git-hook-shared.ts index b7657a705..d4e09bf79 100644 --- a/packages/react-doctor/src/cli/utils/git-hook-shared.ts +++ b/packages/react-doctor/src/cli/utils/git-hook-shared.ts @@ -35,6 +35,10 @@ export const runGitRaw = (projectRoot: string, args: ReadonlyArray): str encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: RUN_GIT_MAX_BUFFER_BYTES, + env: { + ...process.env, + GIT_DIR: undefined, + }, }); } catch { return null; diff --git a/packages/react-doctor/tests/find-staged-snapshot-divergences.test.ts b/packages/react-doctor/tests/find-staged-snapshot-divergences.test.ts index 1fdbeccc7..e3ba0f9c3 100644 --- a/packages/react-doctor/tests/find-staged-snapshot-divergences.test.ts +++ b/packages/react-doctor/tests/find-staged-snapshot-divergences.test.ts @@ -146,4 +146,46 @@ describe("findStagedSnapshotDivergences", () => { it("ignores an ignored configuration status entry", () => { expect(parseStagedSnapshotDivergences("!! .opencode/package.json\0")).toEqual([]); }); + + it("accepts staged files without false divergences when GIT_DIR is set in a linked worktree", () => { + const mainDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "rd-main-")); + temporaryDirectories.push(mainDirectory); + const linkedDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "rd-linked-")); + temporaryDirectories.push(linkedDirectory); + + fs.mkdirSync(path.join(mainDirectory, "src"), { recursive: true }); + fs.writeFileSync(path.join(mainDirectory, "package.json"), '{"dependencies":{"react":"19"}}\n'); + fs.writeFileSync(path.join(mainDirectory, "doctor.config.json"), '{"rules":{}}\n'); + fs.writeFileSync(path.join(mainDirectory, "src/app.tsx"), "export const App = () => null;\n"); + + execFileSync("git", ["init", "-q", "-b", "main"], { cwd: mainDirectory }); + execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: mainDirectory }); + execFileSync("git", ["config", "user.name", "test"], { cwd: mainDirectory }); + execFileSync("git", ["config", "commit.gpgsign", "false"], { cwd: mainDirectory }); + execFileSync("git", ["add", "."], { cwd: mainDirectory }); + execFileSync("git", ["commit", "-q", "-m", "init"], { cwd: mainDirectory }); + + execFileSync("git", ["worktree", "add", "-b", "feature", linkedDirectory, "main"], { + cwd: mainDirectory, + }); + + fs.writeFileSync( + path.join(linkedDirectory, "src/app.tsx"), + "export const App = () =>
;\n", + ); + execFileSync("git", ["add", "src/app.tsx"], { cwd: linkedDirectory }); + + const gitDir = execFileSync("git", ["rev-parse", "--git-dir"], { + cwd: linkedDirectory, + encoding: "utf8", + }).trim(); + const originalGitDir = process.env.GIT_DIR; + try { + process.env.GIT_DIR = gitDir; + expect(findStagedSnapshotDivergences(linkedDirectory)).toEqual([]); + } finally { + if (originalGitDir === undefined) delete process.env.GIT_DIR; + else process.env.GIT_DIR = originalGitDir; + } + }); });