Skip to content

Commit 3100b39

Browse files
Phlogistiqueclaude
andcommitted
Fix stuck PRs from incomplete conflict-resolution comment
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>
1 parent 908602b commit 3100b39

2 files changed

Lines changed: 34 additions & 43 deletions

File tree

tests/test_e2e.sh

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -878,32 +878,37 @@ else
878878
fi
879879

880880

881-
# 12. Resolve conflict manually
882-
echo >&2 "12. Resolving conflict manually on feature3..."
881+
# 12. Resolve the conflict by following the comment the action posted.
882+
echo >&2 "12. Resolving conflict on feature3 by following the posted comment..."
883883
log_cmd git checkout feature3
884-
# Ensure we have the latest main which includes the PR2 merge commit AND the conflicting change on main
885884
log_cmd git fetch origin
886-
# Now, perform the merge that the action tried and failed
887-
echo >&2 "Attempting merge of origin/main into feature3..."
888-
if git merge origin/main; then
889-
echo >&2 "❌ Conflict Resolution Failed: Merge of main into feature3 succeeded unexpectedly (no conflict?)"
890-
log_cmd git status
891-
log_cmd git log --graph --oneline --all
885+
# Run the merge commands from the comment verbatim, resolving any conflict by
886+
# keeping feature3's side. Following the comment must leave feature3 cleanly
887+
# mergeable into its new base; otherwise the synchronize-triggered continuation
888+
# can never make progress and the conflict label stays stuck.
889+
COMMENT_MERGES=$(echo "$CONFLICT_COMMENT" | grep -E '^git merge' || true)
890+
if [[ -z "$COMMENT_MERGES" ]]; then
891+
echo >&2 "❌ Verification Failed: conflict comment lists no 'git merge' commands to follow."
892+
echo >&2 "$CONFLICT_COMMENT"
893+
exit 1
894+
fi
895+
HIT_CONFLICT=false
896+
while IFS= read -r cmd; do
897+
echo >&2 "Following comment: $cmd"
898+
if ! log_cmd bash -c "$cmd"; then
899+
echo >&2 "Conflict during '$cmd'; resolving by keeping feature3's side..."
900+
log_cmd git checkout --ours file.txt
901+
log_cmd git add file.txt
902+
log_cmd git commit --no-edit
903+
HIT_CONFLICT=true
904+
fi
905+
done <<< "$COMMENT_MERGES"
906+
if [[ "$HIT_CONFLICT" != "true" ]]; then
907+
echo >&2 "❌ Verification Failed: following the comment hit no conflict; scenario expected one."
892908
exit 1
893-
else
894-
echo >&2 "Merge conflict occurred as expected. Resolving..."
895-
# Check status to confirm conflict
896-
log_cmd git status
897-
# Resolve conflict - keep feature3's version (ours) of the conflicting file
898-
# This preserves both line 2 (Feature 3 content) and line 7 (Feature 3 conflicting change)
899-
log_cmd git checkout --ours file.txt
900-
echo "Resolved file.txt content:"
901-
cat file.txt
902-
log_cmd git add file.txt
903-
# Use 'git commit' without '-m' to use the default merge commit message
904-
log_cmd git commit --no-edit
905-
echo >&2 "Conflict resolved and committed."
906909
fi
910+
echo >&2 "Resolved file.txt content:"
911+
cat file.txt
907912
log_cmd git push origin feature3
908913
echo >&2 "Pushed resolved feature3."
909914

update-pr-stack.sh

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,6 @@ has_squash_commit() {
4545
&& git merge-base --is-ancestor SQUASH_COMMIT "$BRANCH"
4646
}
4747

48-
format_branch_list_for_text() {
49-
for ((i=1; i<=$#; i++)); do
50-
case $i in
51-
1) format='`%s`';;
52-
$#) format=', and `%s`';;
53-
*) format=', `%s`';;
54-
esac
55-
printf "$format" "${!i}"
56-
done
57-
}
58-
5948
update_direct_target() {
6049
local BRANCH="$1"
6150
local BASE_BRANCH="$2"
@@ -91,24 +80,21 @@ update_direct_target() {
9180
{
9281
echo "### ⚠️ Automatic update blocked by merge conflicts"
9382
echo
94-
echo -n "I tried to merge "
95-
format_branch_list_for_text "${CONFLICTS[@]}"
96-
echo " into this branch while updating the pull request stack and hit conflicts."
83+
echo "I hit a merge conflict while updating this pull request after its base branch was squash-merged. Please resolve it by hand by running these in order:"
9784
echo
9885
echo "#### How to resolve"
9986
echo '```bash'
10087
echo "git fetch origin"
10188
echo "git switch $BRANCH"
102-
for conflict in "${CONFLICTS[@]}"; do
103-
echo "git merge $conflict"
104-
echo "# ..."
105-
echo '# fix conflicts, for instance with `git mergetool`'
106-
echo "# ..."
107-
echo "git commit"
108-
done
89+
echo "git merge origin/$MERGED_BRANCH"
90+
echo "git merge $(git rev-parse SQUASH_COMMIT~)"
91+
echo "# record the squash commit as merged without re-applying its changes:"
92+
echo "git merge -s ours $(git rev-parse SQUASH_COMMIT)"
10993
echo "git push"
11094
echo '```'
11195
echo
96+
echo 'If a merge stops with conflicts, fix them (for instance with `git mergetool`), `git commit`, then run the next command.'
97+
echo
11298
echo "Once you push, this action will resume and finish updating this pull request."
11399
} | log_cmd gh pr comment "$BRANCH" -F -
114100
# Create the label if it doesn't exist, then add it to the PR

0 commit comments

Comments
 (0)