Skip to content
Open
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
40 changes: 39 additions & 1 deletion apps/server/src/git/Layers/GitManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,45 @@ export const makeGitManager = Effect.fn("makeGitManager")(function* () {
}

const baseBranch = yield* resolveBaseBranch(cwd, branch, details.upstreamRef, headContext);
const rangeContext = yield* gitCore.readRangeContext(cwd, baseBranch);

// Fetch the remote tracking ref for the base branch so that the range
// context reflects any upstream changes (e.g. previously merged PRs).
// Without this fetch the local ref can be stale, causing readRangeContext
// to include commits/diffs that were already merged upstream (#1487).
const rangeRef = yield* Effect.gen(function* () {
// If baseBranch already contains a remote prefix, use it as-is.
if (baseBranch.includes("/")) {
return baseBranch;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slash check misidentifies local branches as remote refs

Medium Severity

The baseBranch.includes("/") check is intended to detect remote-prefixed refs like origin/main, but it incorrectly matches any branch name containing a slash (e.g., release/1.0, feature/main, hotfix/critical). These are common local branch naming conventions. When resolveBaseBranch returns such a name — via git config, extractBranchFromRef, or getDefaultBranch — the code skips the remote fetch and uses the potentially stale local ref, defeating the fix for issue #1487 in those cases.

Fix in Cursor Fix in Web

}
// Try to fetch the base branch from the remote and use the remote
// tracking ref for range computation. Prefer the head context's
// remote when available (e.g. fork remotes) and fall back to "origin".
const remoteName = headContext.remoteName ?? "origin";
const remoteRef = `${remoteName}/${baseBranch}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fork workflows fetch base branch from wrong remote

Medium Severity

In cross-repository (fork) workflows, headContext.remoteName is the remote for the feature branch's push target (the fork), not the upstream repo where the PR base branch lives. Fetching the base branch (e.g., main) from the fork remote can retrieve a stale or missing ref, potentially making the range context worse than the original local ref. For example, when origin = upstream and the branch pushes to myfork, the old code used local main (tracking upstream), but the new code fetches myfork/main (the fork's possibly-never-synced main).

Fix in Cursor Fix in Web

yield* gitCore.execute({
operation: "runPrStep.fetchBaseBranch",
cwd,
args: [
"fetch",
"--quiet",
"--no-tags",
remoteName,
`+refs/heads/${baseBranch}:refs/remotes/${remoteRef}`,
],
allowNonZeroExit: true,
timeoutMs: 30_000,
});
// Verify the remote ref exists after fetch; if it does, prefer it.
const verifyResult = yield* gitCore.execute({
operation: "runPrStep.verifyRemoteRef",
cwd,
args: ["rev-parse", "--verify", remoteRef],
allowNonZeroExit: true,
});
return verifyResult.code === 0 ? remoteRef : baseBranch;
}).pipe(Effect.catch(() => Effect.succeed(baseBranch)));

const rangeContext = yield* gitCore.readRangeContext(cwd, rangeRef);

const generated = yield* textGeneration.generatePrContent({
cwd,
Expand Down
Loading