Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-staged-git-dir-worktree.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions packages/react-doctor/src/cli/utils/git-hook-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const runGitRaw = (projectRoot: string, args: ReadonlyArray<string>): str
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
maxBuffer: RUN_GIT_MAX_BUFFER_BYTES,
env: {
...process.env,
GIT_DIR: undefined,
},
});
} catch {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => <div />;\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;
}
});
});
Loading