4343
4444cd " $REPO_ROOT "
4545
46- # ── Step 0: PR status check ─────────────────────── ────────────────────────────
47- # Dynamically fetch all PRs we authored on upstream (open + recently merged ).
48- # No hardcoded numbers — idempotent as PRs come and go .
46+ # ── Step 0: PR status check + patch reality check ────────────────────────────
47+ # PR status from GitHub (proxy — useful but not authoritative ).
48+ # git cherry is the source of truth: + = genuinely not in upstream, - = already absorbed .
4949echo " ▶ Checking our upstream PRs on $UPSTREAM_REPO ..."
5050
5151PR_CHECK_OK=true
52+ BRANCHES_TO_DELETE=()
5253
5354if ! command -v gh & > /dev/null; then
5455 echo " ⚠ gh CLI not found — skipping PR check"
5556elif ! gh auth status & > /dev/null 2>&1 ; then
5657 echo " ⚠ gh not authenticated — skipping PR check"
5758else
58- # Fetch all PRs authored by us: open ones + merged in last 30 days
5959 PRS_JSON=" $( gh pr list \
6060 --repo " $UPSTREAM_REPO " \
6161 --author " @me" \
7373 echo " ──────────────────────────────────────────────────────────────────"
7474
7575 HAS_OPEN=false
76- BRANCHES_TO_DELETE=()
7776 CURRENT_BRANCH_NOW=" $( git rev-parse --abbrev-ref HEAD) "
7877
7978 while IFS= read -r pr; do
8584 case " $state " in
8685 MERGED)
8786 icon=" [MERGED]"
88- # Queue branch for cleanup if it exists locally and we're not on it
8987 if [[ " $branch " != " $CURRENT_BRANCH_NOW " ]] && git show-ref --verify --quiet " refs/heads/$branch " ; then
9088 BRANCHES_TO_DELETE+=(" $branch " )
9189 fi
@@ -108,35 +106,57 @@ for pr in prs:
108106" )
109107
110108 echo " ──────────────────────────────────────────────────────────────────"
111-
112109 if $HAS_OPEN ; then
113- echo " ⚠ Some PRs are still open — we carry those patches locally."
114- echo " They will be included in the rebase until upstream merges them."
110+ echo " ⚠ Some PRs are still open — patches carried locally until upstream merges them."
115111 else
116112 echo " ✓ All our PRs are merged — patch stack should be clean after rebase."
117113 fi
114+ echo " "
115+ fi
116+ fi
118117
119- # Clean up local + fork branches for merged PRs
120- if [[ ${ # BRANCHES_TO_DELETE[@]} -gt 0 ]] ; then
121- echo " "
122- echo " ── Cleaning up merged branches ────── ─────────────────────────────────"
123- for b in " ${BRANCHES_TO_DELETE[@]} " ; do
124- # Local branch — force delete since rebase may have changed SHAs
125- if git branch -D " $b " 2> /dev/null ; then
126- echo " ✓ Deleted local branch: $b "
127- fi
128- # Fork remote branch — best-effort, ignore if already gone
129- if git push " $FORK_REMOTE " --delete " $b " 2> /dev/null ; then
130- echo " ✓ Deleted fork remote branch: $b "
131- else
132- echo " ℹ Fork branch already gone or not found: $b "
133- fi
134- done
135- echo " ────────────────────────────────────────────────────────────────────── "
118+ # ── Patch reality check via git cherry ───────────────────────────────────────
119+ # Authoritative: checks actual code diff, not just PR state.
120+ # Catches squash-merges and closed-without-merge where PR state lies.
121+ echo " ── Patch stack vs upstream (git cherry) ─────────────────────────────────"
122+ CHERRY_OUT= " $( git cherry -v " $UPSTREAM_REMOTE / $UPSTREAM_BRANCH " HEAD 2> /dev/null || true ) "
123+ if [[ -z " $CHERRY_OUT " ]] ; then
124+ echo " ✓ No local patches — branch is identical to upstream "
125+ else
126+ ABSORBED=0
127+ while IFS= read -r line ; do
128+ marker= " ${line : 0 : 1} "
129+ msg= " ${line : 2} "
130+ if [[ " $marker " == " - " ]] ; then
131+ echo " - [ABSORBED] $msg "
132+ ABSORBED= $(( ABSORBED + 1 ))
133+ else
134+ echo " + [PENDING ] $msg "
136135 fi
136+ done <<< " $CHERRY_OUT"
137+ if [[ $ABSORBED -gt 0 ]]; then
137138 echo " "
139+ echo " ⚠ $ABSORBED commit(s) already absorbed by upstream — rebase will drop them."
138140 fi
139141fi
142+ echo " ─────────────────────────────────────────────────────────────────────────"
143+
144+ # ── Cleanup merged branches ───────────────────────────────────────────────────
145+ if [[ ${# BRANCHES_TO_DELETE[@]} -gt 0 ]]; then
146+ echo " "
147+ echo " ── Cleaning up merged branches ───────────────────────────────────────"
148+ for b in " ${BRANCHES_TO_DELETE[@]} " ; do
149+ if git branch -D " $b " 2> /dev/null; then
150+ echo " ✓ Deleted local branch: $b "
151+ fi
152+ if git push " $FORK_REMOTE " --delete " $b " 2> /dev/null; then
153+ echo " ✓ Deleted fork remote branch: $b "
154+ else
155+ echo " ℹ Fork branch already gone: $b "
156+ fi
157+ done
158+ echo " ──────────────────────────────────────────────────────────────────────"
159+ fi
140160
141161if $PR_CHECK_ONLY ; then
142162 exit 0
0 commit comments