From a0f3105ab96fe19886068ee63647ea6de37c150e Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 2 Apr 2026 15:26:54 -0500 Subject: [PATCH] Fix inter-branch-merge to create proper merge commit when using ResetToTargetPaths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When ResetToTargetPaths is configured, the script creates the merge branch from the source branch HEAD and only resets specified files to the target branch. This means the merge branch is missing all target-only content (APIs, platform fixes, version updates, etc.) — it's a linear commit off source, not a real merge. This causes: - Build failures from missing target branch fixes (nullable annotations, platform version mismatches, etc.) - Merge conflicts when the PR is completed because the target branch's changes were never incorporated The fix creates a proper merge commit when ResetToTargetPaths is used: 1. Start the merge branch from the target branch (not source) 2. Merge source into it with --no-ff to create a merge commit 3. Use -X theirs to auto-resolve conflicts (ResetToTargetPaths will overwrite target-wins files in the next step anyway) 4. Then apply ResetToTargetPaths as before Without ResetToTargetPaths, the original behavior is preserved — the branch is created from source and GitHub's merge button does the merge. Discovered in dotnet/maui PR #34789 where the main→net11.0 merge was missing all net11.0-specific content (Directory.Build.props TFMs, nullable fixes, PublicAPI entries) because the script never merged net11.0 into the branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../workflows/scripts/inter-branch-merge.ps1 | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scripts/inter-branch-merge.ps1 b/.github/workflows/scripts/inter-branch-merge.ps1 index c05c2c87895..8c05d117617 100644 --- a/.github/workflows/scripts/inter-branch-merge.ps1 +++ b/.github/workflows/scripts/inter-branch-merge.ps1 @@ -220,13 +220,32 @@ try { Write-Host $committersList $mergeBranchName = "merge/$MergeFromBranch-to-$MergeToBranch" - Invoke-Block { & git checkout -B $mergeBranchName } - # Reset specified files to target branch if ResetToTargetPaths is configured + # When ResetToTargetPaths is configured, we need to create a proper merge commit + # so that the target branch content is included. Without this, the merge branch + # would just be the source branch with some files overwritten, missing all + # target-only changes (APIs, fixes, platform versions, etc.). if ($ResetToTargetPaths) { + # Configure git user for the merge commit + Invoke-Block { & git config user.name "github-actions[bot]" } + Invoke-Block { & git config user.email "41898282+github-actions[bot]@users.noreply.github.com" } + + # Start from the target branch and merge source into it + Invoke-Block { & git checkout -B $mergeBranchName "origin/$MergeToBranch" } + + # Merge source branch. Use -X theirs to auto-resolve conflicts in favor of + # the source branch, since ResetToTargetPaths will overwrite target-wins files + # in the next step anyway. + Invoke-Block { & git merge --no-ff "origin/$MergeFromBranch" -X theirs -m "Merge branch '$MergeFromBranch' into $MergeToBranch" } + $patterns = $ResetToTargetPaths -split ";" ResetFilesToTargetBranch $patterns $MergeToBranch } + else { + # Without ResetToTargetPaths, the original behavior is fine: create a branch + # from the source and let GitHub's merge button do the actual merge. + Invoke-Block { & git checkout -B $mergeBranchName } + } $remoteName = 'origin' $prOwnerName = $RepoOwner