Repository navigation
Support merged-worktree cleanup for PRs targeting release branches or stack parents #14758
Description
Activity
Note
Grok responding on behalf of Julius.
Triage
Thanks for keeping this separate from the squash-merge fix, @tris203. I confirmed the behavior on
main(54084ae). It's the documented policy, not a regression. Delete merged worktrees only goes ahead when the worktree head is an ancestor of the primary remote's default branch, and a non-ancestor returns before the merged pull request is ever read. The settings copy matches that. Your local repro checks out too: after a normal merge intoreleaseor a stack parent,git merge-base --is-ancestor feature mainfails, while the same check against the target succeeds.A possible narrow scope (Julius still needs to approve the direction)
This would extend only Delete merged worktrees. A completed PR merged into any non-default base, whether a release branch or a stack parent, could qualify without waiting for that target to reach the default branch, with no special-casing by branch name. On top of the existing idle, ownership, clean-checkout, ignored-file, and final policy and
HEADchecks, all of these would need to hold:- A fresh PR read for the branch says
merged, and its head ref is the worktree branch. - Its base ref isn't the project's default branch.
- That base ref is fetched from the same primary remote, and the current
HEADis an ancestor of the fetched tip. GitHub's merged state alone isn't enough proof.
The worktree would be kept when:
- the target branch has been deleted, or fetching or resolving it fails
HEADisn't an ancestor of the fetched target, which covers a later local commit, a squash or rebase onto the target, or a target that was reset- the PR is open, closed without merging, or missing, the lookup fails, or the head branch doesn't match
- the base ref isn't on the primary remote, so there's no new target-repo resolver and no change to how the default branch is chosen
Everything else stays as it is. The unchanged-worktree rule stays a default-branch ancestry check, even when both rules are on. The default-branch path doesn't change. Squash and rebase merges into a non-default target stay out of scope, because the exact-head check from #14742 is only for a default-branch base. Only base refs that are a single branch name safe for the existing fetch refspec would be used.
If this goes ahead, the settings copy and storage guide would need to describe both proofs. Tests should cover:
- a normal merge into a release branch or stack parent
- a deleted target
- a later local commit
- a closed-unmerged PR
- a failed lookup
- unchanged-only cleanup
- a squash onto a non-default target still being kept
Please wait for a maintainer go-ahead on this issue before opening a PR.
- A fresh PR read for the branch says
- addedenhancementRequested improvement or new capability.Requested improvement or new capability.via-triageFiled through npx t3 triageFiled through npx t3 triage
on Oct 2, 2026
Before submitting
Area
apps/server — automatic merged-worktree cleanup, shared by all clients.
Problem and scope
A feature PR can be merged into a release branch or its stack parent while the project's default branch does not yet contain its commits. Delete merged worktrees retains that feature checkout, even after an ordinary merge that preserves commit ancestry.
This is an intentional, documented policy limitation, not a regression or a claim of prior approval. The current rule requires ancestry in the primary remote's default branch. #14742's triage explicitly excludes PRs merged into release branches or stack parents from its focused squash-merge fix.
This issue requests separate maintainer triage of that non-default-target case, following #14651's request to separate target-selection behavior. It concerns only Delete merged worktrees, not the separate unchanged-worktree rule.
Steps to reproduce
T3 conditions:
release, or against a stack parent that has not landed inmain.main.The ancestry condition can be reproduced independently without T3 or a GitHub repository. This runs both target cases in new temporary repositories; neither uses squash:
Observed output:
Expected behavior / requested triage decision
Consider allowing merged-worktree cleanup for the completed feature PR without waiting for its target to reach the default branch, while preserving the branch and thread history.
The key scope question is whether a freshly confirmed merged PR is enough for its otherwise eligible checkout to be removed when the target is a release branch or an unmerged stack parent, or whether cleanup should continue waiting for default-branch integration. Please establish that policy and the required evidence before implementation. If eligibility depends on reading the target branch, the behavior when that branch has since been deleted also needs to be explicit.
This request does not change unchanged-worktree cleanup, the existing default-branch ancestry fallback, ignored-file protection, or introduce an unrelated remote/default resolver. Existing ownership, clean-checkout, activity and final policy/HEAD checks remain. A stale PR snapshot, closed-unmerged PR or later unmerged local commit must not be treated as proof that the current checkout was merged.
Actual behavior
Cleanup fetches the primary remote's default branch, tests whether the worktree head is its ancestor, and returns on failure before querying the PR's merged state. The completed child checkout stays until its commits reach the default branch or another cleanup rule qualifies it.
The settings description matches this existing policy. The requested behavior would therefore be an intentional extension, independent of squash-merge detection.
Impact
Completed release/stack child worktrees continue occupying disk despite their PR being merged. Work is not blocked and branches/history are not lost.
Version or commit
Upstream
mainat54084ae1e6c32809db040e4fa571c80fdf2d8ae4.Environment and verification limits
Linux; the script above was run in isolated local Git repositories. Current cleanup source and maintainer comments were inspected. An integrated T3 cleanup run and live GitHub PR merges were not performed; the T3 result is source-traced, not a claimed application test.
Workaround
Wait for the target's commits to reach the default branch, or use the existing inactivity cleanup rule. Those have different timing from cleanup of the already-merged feature PR.