feat: gw cleanup won't delete a base branch open child PRs still target - #49
Merged
Conversation
Deleting a branch that is the base of an open PR makes GitHub close that PR. In the stacked flow, `gw await <base-pr>` fires `gw cleanup` the moment the base merges — exactly when a child PR is most likely still targeting it — so the destructive timing is the default, not a corner case. Before deleting a merged branch's remote, cleanup now lists open PRs whose base is that branch (gh pr list --base). If any exist it skips ONLY the remote deletion (local cleanup and home switch still happen) and tells the user to `gw sync` the children first. On a query error it skips conservatively too. This keeps the base branch alive so child `gw sync` can rebase --onto it. - github: open_prs_with_base + parse_pr_list_json (+ unit tests) - cleanup: remote_deletion_blocked_by_children guard Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
zawakin
added a commit
that referenced
this pull request
Jun 29, 2026
gw sync ran `git rebase origin/main`, which on a stacked branch re-applies the base PR's commits too — doubled and conflict-prone once the base was squash-merged. Use `git rebase --onto origin/main origin/<old-base>` so only this branch's own commits (old-base..HEAD) are replayed. Also reorder to rebase -> update PR base -> push. Moving the PR base first would leave GitHub showing the new base while the branch still carried the old commits if the rebase then failed. The old base's remote-tracking ref still points at its pre-merge tip because cleanup now keeps a base branch alive while open child PRs target it (#49). - git: add rebase_onto - git tests: prove --onto replays only the child's commits after a squash merge Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
zawakin
added a commit
that referenced
this pull request
Jun 29, 2026
The pre-PR restack hint (StackedBaseMerged) used the base branch NAME as the `git rebase --onto` boundary. But a child with no PR yet isn't protected by the cleanup guard (#49 only sees open child PRs), so the base branch may be deleted before the child opens its PR — leaving the name unresolvable. gw new --stack now also records the base tip SHA (branch.<child>.gwBaseSha), which equals the fork point since --stack branches off the current HEAD. The StackedBaseMerged hint prefers that SHA as the `--onto` boundary, so it still resolves after the base branch is gone. gw sync clears both keys on restack; branch deletion clears the rest. - git: branch_base_sha / set_branch_base_sha; unset_branch_base clears both keys - new: record gwBaseSha alongside gwBase - next_action/status: thread recorded_base_sha into StackedBaseMerged's hint Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
Phase 4-B / Guard B:
gw cleanupno longer deletes a remote branch that open child PRs still use as their base.Deleting a branch that is the base of an open PR makes GitHub close that PR. In the stacked flow,
gw await <base-pr>runsgw cleanupthe instant the base merges — exactly when a child PR is most likely still targeting it — so the destructive timing is the default, not a corner case.Before deleting a merged branch's remote, cleanup now lists open PRs whose base is that branch (
gh pr list --base <branch> --state open):gw syncto restack each child first.Net effect: the base branch stays alive until its children are restacked — which is also what the upcoming
gw sync --onto <base>fix needs.Changes
github:open_prs_with_base+parse_pr_list_json(with unit tests for both list parsing and the client query).cleanup:remote_deletion_blocked_by_childrenguard inserted before the merged-branch remote deletion.Test
parser:parse_pr_list_json(array + empty).github:open_prs_with_baselists children / empty (mock executor).mise run verifypasses. (cleanup's wiring is exercised only when a merged PR is confirmed, which the file-remote integration tests don't hit, so the guard logic is covered at the client/parser unit layer.)Sequence
This is step 2 of the stacked-restack package. Next: step 3 —
gw syncusesgit rebase --onto origin/main <old-base>(now safe because this PR keeps the base alive); step 4 — record base SHA atgw new --stackfor the pre-PR fallback.🤖 Generated with Claude Code