Fix stuck PRs from incomplete conflict-resolution comment#32
Closed
Phlogistique wants to merge 1 commit into
Closed
Fix stuck PRs from incomplete conflict-resolution comment#32Phlogistique wants to merge 1 commit into
Phlogistique wants to merge 1 commit into
Conversation
Phlogistique
force-pushed
the
fix-conflict-comment-incomplete-merge-sequence
branch
2 times, most recently
from
May 29, 2026 14:40
efb2c42 to
a75b7da
Compare
When updating a descendant branch after its parent PR was squash-merged hits a merge conflict, the bot posts a comment telling the author how to finish by hand. That comment listed only the ref that conflicted, so a human following it ran a single `git merge` and ended up with a branch still missing the parent-branch merge and the `-s ours` squash record — never mergeable into its new base, so it stayed stuck. The sequence is the same whichever merge conflicts, so the comment now prints it in full: merge the parent branch, merge the pre-squash target, then record the squash with `-s ours`. This fixes the comment only; the author runs the steps by hand. The e2e conflict scenario used to resolve by merging the base directly, so it never exercised the comment. It now follows the comment's commands verbatim, proving a human who follows them ends up mergeable. Diagnosed on sensei #7987. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phlogistique
force-pushed
the
fix-conflict-comment-incomplete-merge-sequence
branch
from
May 29, 2026 14:44
a75b7da to
3100b39
Compare
Phlogistique
added a commit
that referenced
this pull request
May 29, 2026
Alternative to #32 for the same stuck-PR bug — pick one. After a parent PR is squash-merged, updating a descendant branch runs three merges: the parent branch, the target's pre-squash state, then the squash recorded with `-s ours`. When the pre-squash merge conflicted, the action commented and labeled without pushing anything, so the head was left missing both the base merge and the squash record. The branch never became mergeable, and because GitHub skips `pull_request` workflows on a PR that conflicts with its base, the `synchronize` event that resumes the action never fired again — permanently stuck. This splits the work so the user only resolves the genuine conflict: - When the base-branch merge is clean and only the pre-squash merge conflicts, push the base merge to the branch before commenting and labeling. The head stays a descendant of its base, so the PR stays mergeable and the resume trigger keeps firing. If the base merge itself conflicts there is nothing safe to pre-push, so the existing comment-and-label fallback runs. - After the user resolves and pushes, continue_after_resolution records the squash with `-s ours` and pushes before retargeting. The synchronize payload is the child PR, so the squash commit and new target are reconstructed from the merged parent PR (its merge commit and base). The conflict comment is unchanged: it already lists the genuine conflict. Offline test covers both halves: the squash-merge run pushes the base merge before the unchanged comment, and the follow-up run records the squash so the branch ends up mergeable into the new target. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phlogistique
added a commit
that referenced
this pull request
Jun 1, 2026
Alternative to #32 for the same stuck-PR bug. Pick one. Background: when a parent PR is squash-merged, the action brings each child branch up to date with three merges: the parent branch (the base-branch merge), the trunk as it stood just before the squash landed (`SQUASH_COMMIT~`), and the squash itself recorded with `-s ours` so the child's diff against its new base stays clean. When the pre-squash trunk merge conflicts, the action asks the user to resolve, and a follow-up run triggered by the user's push finishes the job. Two separate bugs left a conflicting child PR broken: 1. **The follow-up run never finished the job.** It removed the conflict label, retargeted the PR, and deleted the old base branch, but it never recorded the squash. The synthetic merge commit that keeps the child's diff against its new base clean was never created, and because the label was gone the action would never revisit the PR. 2. **Even with that fixed, the recipe could push the user into an unrecoverable state.** The conflict comment asked the user to merge only the conflicting ref, starting from a head that did not contain the base-branch merge. When that merge is clean the head is clean against its base going in, so the only thing that can make it conflict with the base is the user's own resolution. If resolving the `SQUASH_COMMIT~` conflict produced content that conflicts with the parent branch, the user's push left the head conflicting with its base. GitHub does not run `pull_request` workflows on a PR that conflicts with its base, so the follow-up run never fired and the PR was stuck for good. This PR fixes both: - Push the base-branch merge before commenting, when it is clean. The head then always contains it, so the parent branch is an ancestor and no resolution can make the head conflict with its base. The PR stays mergeable and the synchronize trigger keeps working. If the base merge itself conflicts there is nothing safe to pre-push, so the existing comment-and-label fallback runs. - `continue_after_resolution` now records the squash with `-s ours` and pushes before retargeting. The synchronize payload is the child PR, so the squash commit and new target are reconstructed from the merged parent PR (its merge commit and base). Pushing the base merge leaves the user's local branch behind origin, so the conflict comment now starts the recipe with `git pull --ff-only origin <branch>`. Without it the user resolves on a stale head and the final push is rejected as non-fast-forward. The comment still lists only the genuine conflict to merge. The e2e conflict scenario already triggers this case (clean base merge, conflicting `SQUASH_COMMIT~` merge), so coverage lives there: it checks the action pushed the base merge on top of the pre-conflict head and that the comment asks only for the genuine conflict, then resolves by following the comment verbatim (re-sync included) and checks `continue_after_resolution` records the squash so the branch ends up mergeable into the new target. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
superseded by #33 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When updating a descendant branch after its parent PR was squash-merged hits a merge conflict, the bot posts a comment telling the author how to finish by hand. That comment listed only the ref that conflicted, so a human following it ran a single
git mergeand ended up with a branch still missing the parent-branch merge and the-s ourssquash record — never mergeable into its new base, so it stayed stuck.The sequence is the same whichever merge conflicts, so the comment now prints it in full: merge the parent branch, merge the pre-squash target, then record the squash with
-s ours. This fixes the comment only; the author runs the steps by hand.The e2e conflict scenario used to resolve by merging the base directly, so it never exercised the comment. It now follows the comment's commands verbatim, proving a human who follows them ends up mergeable.
Diagnosed on sensei #7987.