From 968126424fd3d113c5dc56de1cc70f2ea03cef06 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 9 Jun 2026 20:48:57 +0000 Subject: [PATCH] Fix the squash-commit idempotency check to resolve in real action runs has_squash_commit compared the target with a bare branch name like "main". actions/checkout leaves a detached HEAD and creates no local branches, so "main" does not resolve and git exits 128, which the if silently reads as "not up-to-date". The skip branch was therefore dead in CI and only worked in tests, where the test repos have every branch locally. This matters on the resume path: the push that finishes conflict resolution fires a synchronize event while the conflict label is still on. If that second run loses the race against the label removal, the broken check let it re-run the whole merge and push a second redundant synthetic merge commit. Compare against origin/$TARGET_BRANCH instead. With fetch-depth: 0 the remote-tracking ref always exists, so the check works in production while staying correct in tests. --- update-pr-stack.sh | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/update-pr-stack.sh b/update-pr-stack.sh index a2d8ca5..f84e52c 100755 --- a/update-pr-stack.sh +++ b/update-pr-stack.sh @@ -64,9 +64,6 @@ check_env_var() { # Check if a branch already has the squash commit merged (squash-merge mode only) # Requires SQUASH_COMMIT ref to be set via git update-ref -# -# Note: This uses local branch refs. The caller must ensure both branches -# exist locally before calling (e.g., via git checkout). has_squash_commit() { local BRANCH="$1" local BASE="$2" @@ -78,12 +75,11 @@ update_direct_target() { local BRANCH="$1" local BASE_BRANCH="$2" - # Checkout first to ensure the local branch exists (created from origin if - # needed). This allows has_squash_commit to compare local refs, which matters - # for testing where the script may run multiple times in the same repo. log_cmd git checkout "$BRANCH" - if has_squash_commit "$BRANCH" "$TARGET_BRANCH"; then + # The target branch is never checked out, so it has no local ref, only the + # remote-tracking one; a bare $TARGET_BRANCH would not resolve. + if has_squash_commit "$BRANCH" "origin/$TARGET_BRANCH"; then echo "✓ $BRANCH already up-to-date; skipping" return 0 fi