Skip to content

Commit 99ffd28

Browse files
authored
fix: exclude merged upstream commits from diffSize in push_to_pull_request_branch incremental mode (#34139)
1 parent 6a9182b commit 99ffd28

2 files changed

Lines changed: 464 additions & 3 deletions

File tree

actions/setup/js/generate_git_patch.cjs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -442,16 +442,77 @@ async function generateGitPatch(branchName, baseBranch, options = {}) {
442442
// The measurement itself (stream to temp file via `git diff --output`, stat,
443443
// cleanup) is extracted into git_patch_utils.computeIncrementalDiffSize so
444444
// it is O(1) memory and independently unit-testable against a real repo.
445+
//
446+
// When the agent has merged the default branch into the PR branch (to resolve
447+
// conflicts or sync a stale branch), the naive diff base of `origin/<branch>`
448+
// (the PR's old head) inflates diffSize to include all of the default branch's
449+
// new commits — even though those commits are already on origin/<defaultBranch>
450+
// and represent no new content in the PR. Fix: when the merge-base between
451+
// origin/<defaultBranch> and the local branch is NOT an ancestor of the PR's
452+
// current head (baseCommitSha), the agent merged default-branch commits ahead
453+
// of the PR head. Use the merge-base as the effective diff base to exclude those
454+
// merged upstream commits from the size measurement.
455+
let diffBaseForSize = baseCommitSha;
456+
if (mode === "incremental" && baseCommitSha && branchName && defaultBranch) {
457+
try {
458+
let baseBranchRemoteRef = null;
459+
try {
460+
execGitSync(["show-ref", "--verify", "--quiet", `refs/remotes/origin/${defaultBranch}`], { cwd });
461+
baseBranchRemoteRef = `refs/remotes/origin/${defaultBranch}`;
462+
} catch {
463+
// origin/<defaultBranch> not available locally; skip the adjustment
464+
}
465+
if (baseBranchRemoteRef) {
466+
// Only adjust the diff base when baseCommitSha is an ancestor of the local
467+
// branch tip. If it is NOT an ancestor the branch was rewritten (rebase /
468+
// force-push); in that case the merge-base adjustment could undercount by
469+
// ignoring commits that changed relative to the remote, so keep the original
470+
// baseCommitSha as the diff base.
471+
let baseIsAncestorOfBranch = false;
472+
try {
473+
execGitSync(["merge-base", "--is-ancestor", "--", baseCommitSha, branchName], { cwd });
474+
baseIsAncestorOfBranch = true;
475+
} catch {
476+
// baseCommitSha is not an ancestor of branchName (rebase / force-push)
477+
debugLog(`Strategy 1 (incremental): baseCommitSha ${baseCommitSha} is not an ancestor of ${branchName} (rebase/force-push?); skipping merge-base adjustment`);
478+
}
479+
480+
if (baseIsAncestorOfBranch) {
481+
const mb = execGitSync(["merge-base", "--", baseBranchRemoteRef, branchName], { cwd }).trim();
482+
// Check if mb is already an ancestor of baseCommitSha.
483+
// If it is, baseCommitSha is "later" and the agent did NOT merge the default
484+
// branch ahead of the PR head — keep baseCommitSha as the diff base.
485+
// If mb is NOT an ancestor of baseCommitSha, the agent merged default-branch
486+
// commits that are beyond the PR head. Use mb to exclude those commits from
487+
// the incremental diff size measurement.
488+
let mbIsAncestorOfBase = false;
489+
try {
490+
execGitSync(["merge-base", "--is-ancestor", "--", mb, baseCommitSha], { cwd });
491+
mbIsAncestorOfBase = true;
492+
} catch {
493+
// mb is not an ancestor of baseCommitSha
494+
}
495+
if (!mbIsAncestorOfBase) {
496+
debugLog(`Strategy 1 (incremental): agent merged ${defaultBranch} ahead of PR head; using merge-base ${mb} as diff base instead of PR head ${baseCommitSha}`);
497+
diffBaseForSize = mb;
498+
}
499+
}
500+
}
501+
} catch (adjustErr) {
502+
debugLog(`Strategy 1 (incremental): diff-base adjustment failed (${getErrorMessage(adjustErr)}); using original base`);
503+
}
504+
}
505+
445506
let diffSize = null;
446-
if (mode === "incremental" && baseCommitSha && branchName) {
507+
if (mode === "incremental" && diffBaseForSize && branchName) {
447508
diffSize = computeIncrementalDiffSize({
448-
baseRef: baseCommitSha,
509+
baseRef: diffBaseForSize,
449510
headRef: branchName,
450511
cwd,
451512
tmpPath: `${patchPath}.diff.tmp`,
452513
excludedFiles: options.excludedFiles,
453514
});
454-
debugLog(`Final: diffSize=${diffSize ?? "(n/a)"} bytes (baseRef=${baseCommitSha}..${branchName})`);
515+
debugLog(`Final: diffSize=${diffSize ?? "(n/a)"} bytes (baseRef=${diffBaseForSize}..${branchName})`);
455516
}
456517

457518
debugLog(`Final: SUCCESS - patchSize=${patchSize} bytes, patchLines=${patchLines}, diffSize=${diffSize ?? "(n/a)"} bytes, baseCommit=${baseCommitSha || "(unknown)"}`);

0 commit comments

Comments
 (0)