Skip to content

Commit 1ea5db0

Browse files
committed
Fix stale merged-PR rebase boundaries
Cache merged PR heads independently of local branch snapshots and compare fallback cutoffs by ancestry. Backfill existing stacks and preserve worktree recovery boundaries.
1 parent 6721eba commit 1ea5db0

18 files changed

Lines changed: 947 additions & 87 deletions

File tree

‎cmd/checkout.go‎

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -685,13 +685,8 @@ func importRemoteStack(
685685
branchRefs := make([]stack.BranchRef, len(prs))
686686
for i, pr := range prs {
687687
branchRefs[i] = stack.BranchRef{
688-
Branch: pr.HeadRefName,
689-
PullRequest: &stack.PullRequestRef{
690-
Number: pr.Number,
691-
ID: pr.ID,
692-
URL: pr.URL,
693-
Merged: pr.Merged,
694-
},
688+
Branch: pr.HeadRefName,
689+
PullRequest: pullRequestRef(pr, nil),
695690
}
696691
}
697692

@@ -727,12 +722,7 @@ func syncRemotePRState(s *stack.Stack, prs []*github.PullRequest) {
727722
if !ok {
728723
continue
729724
}
730-
s.Branches[i].PullRequest = &stack.PullRequestRef{
731-
Number: pr.Number,
732-
ID: pr.ID,
733-
URL: pr.URL,
734-
Merged: pr.Merged,
735-
}
725+
s.Branches[i].PullRequest = pullRequestRef(pr, s.Branches[i].PullRequest)
736726
s.Branches[i].Queued = pr.IsQueued()
737727
}
738728
}

‎cmd/checkout_test.go‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ func TestCheckout_NumericTarget_MergedBranchDeletedFromRemote(t *testing.T) {
11511151
},
11521152
FindPRByNumberFn: func(number int) (*github.PullRequest, error) {
11531153
prs := map[int]*github.PullRequest{
1154-
10: {ID: "PR_10", Number: 10, HeadRefName: "feat-1", BaseRefName: "main", Merged: true, State: "MERGED", URL: "https://github.com/o/r/pull/10"},
1154+
10: {ID: "PR_10", Number: 10, HeadRefName: "feat-1", HeadRefOID: "merged-head", BaseRefName: "main", Merged: true, State: "MERGED", URL: "https://github.com/o/r/pull/10"},
11551155
11: {ID: "PR_11", Number: 11, HeadRefName: "feat-2", BaseRefName: "feat-1", State: "OPEN", URL: "https://github.com/o/r/pull/11"},
11561156
}
11571157
return prs[number], nil
@@ -1165,6 +1165,24 @@ func TestCheckout_NumericTarget_MergedBranchDeletedFromRemote(t *testing.T) {
11651165
assert.Equal(t, "feat-2", checkedOut)
11661166
assert.Contains(t, output, "Skipping merged branch feat-1")
11671167
assert.Contains(t, output, "Imported stack with 2 branches")
1168+
sf, err := stack.Load(gitDir)
1169+
require.NoError(t, err)
1170+
assert.Equal(t, "merged-head", sf.Stacks[0].Branches[0].PullRequest.MergedHead)
1171+
assert.Empty(t, sf.Stacks[0].Branches[0].Head)
1172+
}
1173+
1174+
func TestSyncRemotePRState_MergedHead(t *testing.T) {
1175+
s := &stack.Stack{Branches: []stack.BranchRef{{
1176+
Branch: "parent", Head: "local",
1177+
PullRequest: &stack.PullRequestRef{Number: 10, Merged: true, MergedHead: "cached"},
1178+
}}}
1179+
syncRemotePRState(s, []*github.PullRequest{{Number: 10, HeadRefName: "parent", Merged: true}})
1180+
assert.Equal(t, "cached", s.Branches[0].PullRequest.MergedHead)
1181+
assert.Equal(t, "local", s.Branches[0].Head)
1182+
1183+
syncRemotePRState(s, []*github.PullRequest{{Number: 11, HeadRefName: "parent", State: "OPEN"}})
1184+
assert.Empty(t, s.Branches[0].PullRequest.MergedHead)
1185+
assert.False(t, s.Branches[0].IsMerged())
11681186
}
11691187

11701188
func TestCheckout_NumericTarget_AllPRsMerged(t *testing.T) {

‎cmd/rebase.go‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,8 @@ func runRebase(cfg *config.Config, opts *rebaseOptions) error {
250250
if startIdx > 0 {
251251
prev := s.Branches[startIdx-1]
252252
if prev.IsMerged() {
253-
if sha, ok := originalRefs[prev.Branch]; ok {
254-
needsOnto = true
255-
ontoOldBase = sha
256-
}
253+
needsOnto = true
254+
ontoOldBase = originalRefs[prev.Branch]
257255
}
258256
}
259257

0 commit comments

Comments
 (0)