Skip to content

Landing many open PRs through one GitHub integration PR: merge commit flips them to Merged by ancestry; 'Closes #1, #2' only closes #1

Several open PRs (some from forks, one draft) were merged locally with git merge --no-ff into an integration branch that was tested as a whole. I wanted to open one PR from that branch, merge it once, and have GitHub show each original PR as Merged (purple, 'merged via #N') rather than closing them by hand or leaving them open. Also wanted the integration PR to close the issues it fixed, so the body ended with Closes #635, #640, #642, #653. After merging: all contained PRs flipped to Merged, but only the first issue in the list closed; the other three stayed open. Unclear which merge method is safe for the PR auto-merge, whether fork PRs count, and whether a PR whose head moved after I merged it would still flip.

1 solution
ranked by outcome — not votes
Accepted

PR state is by ancestry. GitHub marks a pull request Merged when its head commit becomes reachable from its base branch, regardless of which PR brought it there. So: merge each PR's head into the integration branch with a real merge commit (git merge --no-ff pr/N), then merge the integration PR with "Create a merge commit" (gh pr merge --merge). Every contained PR flips to Merged within seconds (observed: 8 PRs, same minute). It works for fork PRs (the check is on the commit SHA) and for draft PRs. It does not work with squash or rebase merge of the integration PR: those rewrite SHAs, the original heads never become ancestors, and the PRs stay open.

Two things to verify before merging:

  1. Each PR's current head is still an ancestor of your branch; a PR that received a commit after you merged it will not flip. Check with
    for n in 468 571 656; do
      h=$(gh pr view $n --json headRefOid,baseRefName -q '[.headRefOid, .baseRefName] | join(" ")')
      git merge-base --is-ancestor ${h%% *} HEAD && echo "#$n in" || echo "#$n MOVED: ${h%% *}"
    done
    and merge the moved head in (git fetch origin refs/pull/N/head:pr/N && git merge --no-ff pr/N).
  2. Each PR targets the same base branch you are merging into. A PR whose base is another feature branch stays open.

Issue closing needs a keyword per reference. GitHub's closing-keyword parser links only keyword #number pairs; in Closes #635, #640, #642, #653 only #635 is linked and auto-closed. Write Closes #635, closes #640, closes #642, closes #653 (or one per line). Issues that were not linked have to be closed by hand (gh issue close N -c '...') after the merge; editing the merged PR's body afterwards does not close them.