Skip to content

Refuse to backport octopus merge commits - #79

Draft
aiolibsbot wants to merge 1 commit into
sanitizers:masterfrom
aiolibsbot:koan/octopus-merge-commit-guard
Draft

aiolibsbot wants to merge 1 commit into
sanitizers:masterfrom
aiolibsbot:koan/octopus-merge-commit-guard

Conversation

@aiolibsbot

@aiolibsbot aiolibsbot commented Sep 17, 2026 •

Copy link
Copy Markdown

What: Refuse to backport a pull request whose merge commit is an octopus commit, instead of cherry-picking it against parent 1.

Why: backport_pr_sync asked git rev-list --merges a yes/no question and passed --mainline 1 on any "yes". For a commit with more than two parents, the diff against parent 1 also contains every other branch merged in the same commit — so patchback opened a backport PR carrying other people's changes and reported it green. A wrong result presented as a success is worse than a failure. Merge queues batching several PRs are the usual source of such a merge_commit_sha. Refs #38.

How: Count parents rather than classify. patchback/merge_commit.py is pure and stdlib-only: count_commit_parents parses a git rev-list --parents -n 1 line; cherry_pick_mainline_args maps the count to flags — none for a regular commit, --mainline 1 for a two-parent merge, UnsupportedMergeCommitError above that. The handler gets one new except branch with its own check-run subtitle. The manual backport guide is deliberately not attached there: its git cherry-pick -m1 step is exactly what would pull in the unrelated branches, so the error text points at the PR's own commits instead.

Testing: 13 tests. Beyond the parser and the mapping, two of them build a real four-parent octopus merge and a real two-parent merge with git and run the actual rev-list invocation, so the parsing is verified against what the command emits rather than a fixture of it. pytest.ini and .github/workflows/tests.yml are byte-identical to the copies on #72/#73/#77, so merge order stays free.


Quality Report

Changes: 5 files changed, 230 insertions(+), 6 deletions(-)

Code scan: clean

Tests: failed (command not found)

Branch hygiene: clean

Generated by Kōan

`backport_pr_sync` probed the commit with `git rev-list --merges` and
passed `--mainline 1` to `git cherry-pick` whenever that said "merge".
That test cannot tell a two-parent merge from an octopus one, and for an
octopus commit the diff against parent 1 also carries every other branch
merged alongside. The backport then succeeded, opened a pull request, and
quietly shipped changes belonging to other pull requests -- a wrong
result reported as a green one. Merge queues batching several pull
requests are the usual way such a commit ends up as a `merge_commit_sha`.

Count the parents instead of asking a yes/no question:

- `patchback/merge_commit.py` holds the two pure, stdlib-only pieces --
  `count_commit_parents` parses a `git rev-list --parents -n 1` line, and
  `cherry_pick_mainline_args` maps the count to the flags: nothing for a
  regular commit, `--mainline 1` for a two-parent merge, and
  `UnsupportedMergeCommitError` beyond that.
- The handler reports the refusal on its own check run, telling the user
  to pick the pull request's own commits. The manual guide is left off
  that path on purpose: its `-m1` step is what would go wrong.

Tests cover the parser and the mapping, and build real octopus and
two-parent merges with `git` so the parsing is checked against what the
command actually emits, not against a fixture of it.

`pytest.ini` and the tests workflow are byte-identical to the ones on the
other open branches, so they merge in any order.

Refs: sanitizers#38

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant