@@ -618,6 +618,107 @@ func TestCheckout_NumericTarget_ClosedMergedPR(t *testing.T) {
618618 assert .False (t , sf .Stacks [0 ].Branches [1 ].PullRequest .Merged )
619619}
620620
621+ func TestCheckout_NumericTarget_MergedBranchDeletedFromRemote (t * testing.T ) {
622+ gitDir := t .TempDir ()
623+ var checkedOut string
624+
625+ restore := git .SetOps (& git.MockOps {
626+ GitDirFn : func () (string , error ) { return gitDir , nil },
627+ CurrentBranchFn : func () (string , error ) { return "main" , nil },
628+ BranchExistsFn : func (name string ) bool {
629+ return name == "main"
630+ },
631+ FetchFn : func (remote string ) error { return nil },
632+ CreateBranchFn : func (name , base string ) error {
633+ // Simulate merged branch deleted from remote: origin/feat-1 doesn't exist
634+ if base == "origin/feat-1" {
635+ return fmt .Errorf ("failed to run git: fatal: not a valid object name: 'origin/feat-1'" )
636+ }
637+ return nil
638+ },
639+ SetUpstreamTrackingFn : func (branch , remote string ) error { return nil },
640+ ResolveRemoteFn : func (branch string ) (string , error ) {
641+ return "origin" , nil
642+ },
643+ CheckoutBranchFn : func (name string ) error {
644+ checkedOut = name
645+ return nil
646+ },
647+ RevParseFn : func (ref string ) (string , error ) {
648+ return "abc123" , nil
649+ },
650+ RevParseMultiFn : func (refs []string ) ([]string , error ) {
651+ shas := make ([]string , len (refs ))
652+ for i := range refs {
653+ shas [i ] = "abc123"
654+ }
655+ return shas , nil
656+ },
657+ })
658+ defer restore ()
659+
660+ require .NoError (t , stack .Save (gitDir , & stack.StackFile {SchemaVersion : 1 , Stacks : []stack.Stack {}}))
661+
662+ cfg , outR , errR := config .NewTestConfig ()
663+ cfg .GitHubClientOverride = & github.MockClient {
664+ ListStacksFn : func () ([]github.RemoteStack , error ) {
665+ return []github.RemoteStack {
666+ {ID : 60 , PullRequests : []int {10 , 11 }},
667+ }, nil
668+ },
669+ FindPRByNumberFn : func (number int ) (* github.PullRequest , error ) {
670+ prs := map [int ]* github.PullRequest {
671+ 10 : {ID : "PR_10" , Number : 10 , HeadRefName : "feat-1" , BaseRefName : "main" , Merged : true , State : "MERGED" , URL : "https://github.com/o/r/pull/10" },
672+ 11 : {ID : "PR_11" , Number : 11 , HeadRefName : "feat-2" , BaseRefName : "feat-1" , State : "OPEN" , URL : "https://github.com/o/r/pull/11" },
673+ }
674+ return prs [number ], nil
675+ },
676+ }
677+
678+ err := runCheckout (cfg , & checkoutOptions {target : "11" })
679+ output := collectOutput (cfg , outR , errR )
680+
681+ require .NoError (t , err )
682+ assert .Equal (t , "feat-2" , checkedOut )
683+ assert .Contains (t , output , "Skipping merged branch feat-1" )
684+ assert .Contains (t , output , "Imported stack with 2 branches" )
685+ }
686+
687+ func TestCheckout_NumericTarget_AllPRsMerged (t * testing.T ) {
688+ gitDir := t .TempDir ()
689+
690+ restore := git .SetOps (& git.MockOps {
691+ GitDirFn : func () (string , error ) { return gitDir , nil },
692+ CurrentBranchFn : func () (string , error ) { return "main" , nil },
693+ })
694+ defer restore ()
695+
696+ require .NoError (t , stack .Save (gitDir , & stack.StackFile {SchemaVersion : 1 , Stacks : []stack.Stack {}}))
697+
698+ cfg , outR , errR := config .NewTestConfig ()
699+ cfg .GitHubClientOverride = & github.MockClient {
700+ ListStacksFn : func () ([]github.RemoteStack , error ) {
701+ return []github.RemoteStack {
702+ {ID : 70 , PullRequests : []int {10 , 11 }},
703+ }, nil
704+ },
705+ FindPRByNumberFn : func (number int ) (* github.PullRequest , error ) {
706+ prs := map [int ]* github.PullRequest {
707+ 10 : {ID : "PR_10" , Number : 10 , HeadRefName : "feat-1" , BaseRefName : "main" , Merged : true , State : "MERGED" , URL : "https://github.com/o/r/pull/10" },
708+ 11 : {ID : "PR_11" , Number : 11 , HeadRefName : "feat-2" , BaseRefName : "feat-1" , Merged : true , State : "MERGED" , URL : "https://github.com/o/r/pull/11" },
709+ }
710+ return prs [number ], nil
711+ },
712+ }
713+
714+ err := runCheckout (cfg , & checkoutOptions {target : "11" })
715+ output := collectOutput (cfg , outR , errR )
716+
717+ assert .ErrorIs (t , err , ErrSilent )
718+ assert .Contains (t , output , "All PRs in this stack have been merged" )
719+ assert .Contains (t , output , "gh stack init" )
720+ }
721+
621722func TestCheckout_NumericTarget_APIError (t * testing.T ) {
622723 gitDir := t .TempDir ()
623724 restore := git .SetOps (& git.MockOps {
0 commit comments