@@ -150,6 +150,12 @@ where
150150 worktree_path : & Path ,
151151 pr_number : u64 ,
152152 ) -> color_eyre:: Result < ( ) > {
153+ let mut detached_for_deletion = false ;
154+ if self . remove_local_branch {
155+ self . detach_worktree_head ( worktree_path) ?;
156+ detached_for_deletion = true ;
157+ }
158+
153159 let mut args = vec ! [
154160 "pr" . to_owned( ) ,
155161 "merge" . to_owned( ) ,
@@ -168,6 +174,9 @@ where
168174 let branch_delete_failed = self . remove_local_branch && gh_branch_delete_failure ( & output) ;
169175
170176 if !output. success && !branch_delete_failed {
177+ if detached_for_deletion {
178+ let _ = self . restore_worktree_branch ( worktree_path, branch) ;
179+ }
171180 return Err ( command_failure ( "gh" , & args, & output) ) ;
172181 }
173182
@@ -187,7 +196,9 @@ where
187196 ) ;
188197 }
189198
190- self . restore_worktree_branch ( worktree_path, branch) ?;
199+ if !self . remove_local_branch || branch_delete_failed {
200+ self . restore_worktree_branch ( worktree_path, branch) ?;
201+ }
191202
192203 if self . remove_remote_branch {
193204 self . delete_remote_branch ( repo_path, branch) ?;
@@ -196,6 +207,24 @@ where
196207 Ok ( ( ) )
197208 }
198209
210+ fn detach_worktree_head ( & mut self , worktree_path : & Path ) -> color_eyre:: Result < ( ) > {
211+ let args = vec ! [
212+ "switch" . to_owned( ) ,
213+ "--detach" . to_owned( ) ,
214+ "HEAD" . to_owned( ) ,
215+ ] ;
216+ let output = self
217+ . runner
218+ . run ( "git" , worktree_path, & args)
219+ . wrap_err ( "failed to detach worktree with `git switch --detach`" ) ?;
220+
221+ if !output. success {
222+ return Err ( command_failure ( "git" , & args, & output) ) ;
223+ }
224+
225+ Ok ( ( ) )
226+ }
227+
199228 fn restore_worktree_branch (
200229 & mut self ,
201230 worktree_path : & Path ,
@@ -449,6 +478,11 @@ mod tests {
449478 "1" . into( ) ,
450479 ] ,
451480 } ,
481+ RecordedCall {
482+ program: "git" . into( ) ,
483+ dir: worktree_path. clone( ) ,
484+ args: vec![ "switch" . into( ) , "--detach" . into( ) , "HEAD" . into( ) ] ,
485+ } ,
452486 RecordedCall {
453487 program: "gh" . into( ) ,
454488 dir: repo_root,
@@ -460,11 +494,6 @@ mod tests {
460494 "--delete-branch" . into( ) ,
461495 ] ,
462496 } ,
463- RecordedCall {
464- program: "git" . into( ) ,
465- dir: worktree_path. clone( ) ,
466- args: vec![ "switch" . into( ) , "feature/test" . into( ) ] ,
467- } ,
468497 ]
469498 ) ;
470499
@@ -615,6 +644,11 @@ mod tests {
615644 "1" . into( ) ,
616645 ] ,
617646 } ,
647+ RecordedCall {
648+ program: "git" . into( ) ,
649+ dir: worktree_path. clone( ) ,
650+ args: vec![ "switch" . into( ) , "--detach" . into( ) , "HEAD" . into( ) ] ,
651+ } ,
618652 RecordedCall {
619653 program: "gh" . into( ) ,
620654 dir: repo_root. clone( ) ,
@@ -626,11 +660,6 @@ mod tests {
626660 "--delete-branch" . into( ) ,
627661 ] ,
628662 } ,
629- RecordedCall {
630- program: "git" . into( ) ,
631- dir: worktree_path. clone( ) ,
632- args: vec![ "switch" . into( ) , "feature/remove" . into( ) ] ,
633- } ,
634663 RecordedCall {
635664 program: "git" . into( ) ,
636665 dir: repo_root,
@@ -858,6 +887,12 @@ mod tests {
858887 success : true ,
859888 status_code : Some ( 0 ) ,
860889 } ) ,
890+ Ok ( CommandOutput {
891+ stdout : String :: new ( ) ,
892+ stderr : String :: new ( ) ,
893+ success : true ,
894+ status_code : Some ( 0 ) ,
895+ } ) ,
861896 Ok ( CommandOutput {
862897 stdout : "Pull request successfully merged" . into ( ) ,
863898 stderr : "failed to delete local branch merge-cmd" . into ( ) ,
@@ -899,6 +934,11 @@ mod tests {
899934 "1" . into( ) ,
900935 ] ,
901936 } ,
937+ RecordedCall {
938+ program: "git" . into( ) ,
939+ dir: worktree_path. clone( ) ,
940+ args: vec![ "switch" . into( ) , "--detach" . into( ) , "HEAD" . into( ) ] ,
941+ } ,
902942 RecordedCall {
903943 program: "gh" . into( ) ,
904944 dir: repo_root. clone( ) ,
@@ -1024,12 +1064,6 @@ mod tests {
10241064 success : true ,
10251065 status_code : Some ( 0 ) ,
10261066 } ) ,
1027- Ok ( CommandOutput {
1028- stdout : String :: new ( ) ,
1029- stderr : String :: new ( ) ,
1030- success : true ,
1031- status_code : Some ( 0 ) ,
1032- } ) ,
10331067 Ok ( CommandOutput {
10341068 stdout : String :: new ( ) ,
10351069 stderr : String :: from ( "fatal: not a git repository" ) ,
@@ -1040,7 +1074,7 @@ mod tests {
10401074
10411075 let mut command = MergePrGithubCommand :: with_runner ( "feature/test" . into ( ) , runner) ;
10421076 let err = command. execute ( & repo) . unwrap_err ( ) ;
1043- assert ! ( err. to_string( ) . contains( "git switch" ) ) ;
1077+ assert ! ( err. to_string( ) . contains( "git switch --detach " ) ) ;
10441078
10451079 assert_eq ! (
10461080 command. runner. calls,
@@ -1066,21 +1100,10 @@ mod tests {
10661100 "1" . into( ) ,
10671101 ] ,
10681102 } ,
1069- RecordedCall {
1070- program: "gh" . into( ) ,
1071- dir: repo_root,
1072- args: vec![
1073- "pr" . into( ) ,
1074- "merge" . into( ) ,
1075- "42" . into( ) ,
1076- "--merge" . into( ) ,
1077- "--delete-branch" . into( ) ,
1078- ] ,
1079- } ,
10801103 RecordedCall {
10811104 program: "git" . into( ) ,
10821105 dir: worktree_path,
1083- args: vec![ "switch" . into( ) , "feature/test " . into( ) ] ,
1106+ args: vec![ "switch" . into( ) , "--detach" . into ( ) , "HEAD ". into( ) ] ,
10841107 } ,
10851108 ]
10861109 ) ;
0 commit comments