@@ -104,6 +104,7 @@ struct rebase_options {
104104 int rebase_merges , rebase_cousins ;
105105 char * strategy , * strategy_opts ;
106106 struct strbuf git_format_patch_opt ;
107+ int reschedule_failed_exec ;
107108};
108109
109110static int is_interactive (struct rebase_options * opts )
@@ -415,6 +416,8 @@ static int run_specific_rebase(struct rebase_options *opts)
415416 argv_array_push (& child .args , opts -> gpg_sign_opt );
416417 if (opts -> signoff )
417418 argv_array_push (& child .args , "--signoff" );
419+ if (opts -> reschedule_failed_exec )
420+ argv_array_push (& child .args , "--reschedule-failed-exec" );
418421
419422 status = run_command (& child );
420423 goto finished_rebase ;
@@ -674,6 +677,11 @@ static int rebase_config(const char *var, const char *value, void *data)
674677 return 0 ;
675678 }
676679
680+ if (!strcmp (var , "rebase.reschedulefailedexec" )) {
681+ opts -> reschedule_failed_exec = git_config_bool (var , value );
682+ return 0 ;
683+ }
684+
677685 return git_default_config (var , value , data );
678686}
679687
@@ -746,6 +754,23 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
746754 return 0 ;
747755}
748756
757+ struct opt_y {
758+ struct string_list * list ;
759+ struct rebase_options * options ;
760+ };
761+
762+ static int parse_opt_y (const struct option * opt , const char * arg , int unset )
763+ {
764+ struct opt_y * o = opt -> value ;
765+
766+ if (unset || !arg )
767+ return -1 ;
768+
769+ o -> options -> reschedule_failed_exec = 1 ;
770+ string_list_append (o -> list , arg );
771+ return 0 ;
772+ }
773+
749774static void NORETURN error_on_missing_default_upstream (void )
750775{
751776 struct branch * current_branch = branch_get (NULL );
@@ -826,6 +851,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
826851 struct string_list strategy_options = STRING_LIST_INIT_NODUP ;
827852 struct object_id squash_onto ;
828853 char * squash_onto_name = NULL ;
854+ struct opt_y opt_y = { .list = & exec , .options = & options };
829855 struct option builtin_rebase_options [] = {
830856 OPT_STRING (0 , "onto" , & options .onto_name ,
831857 N_ ("revision" ),
@@ -903,6 +929,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
903929 OPT_STRING_LIST ('x' , "exec" , & exec , N_ ("exec" ),
904930 N_ ("add exec lines after each commit of the "
905931 "editable list" )),
932+ { OPTION_CALLBACK , 'y' , NULL , & opt_y , N_ ("<cmd>" ),
933+ N_ ("same as --reschedule-failed-exec -x <cmd>" ),
934+ PARSE_OPT_NONEG , parse_opt_y },
906935 OPT_BOOL (0 , "allow-empty-message" ,
907936 & options .allow_empty_message ,
908937 N_ ("allow rebasing commits with empty messages" )),
@@ -920,6 +949,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
920949 "strategy" )),
921950 OPT_BOOL (0 , "root" , & options .root ,
922951 N_ ("rebase all reachable commits up to the root(s)" )),
952+ OPT_BOOL (0 , "reschedule-failed-exec" ,
953+ & options .reschedule_failed_exec ,
954+ N_ ("automatically re-schedule any `exec` that fails" )),
923955 OPT_END (),
924956 };
925957 int i ;
@@ -1216,6 +1248,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
12161248 break ;
12171249 }
12181250
1251+ if (options .reschedule_failed_exec && !is_interactive (& options ))
1252+ die (_ ("--reschedule-failed-exec requires an interactive rebase" ));
1253+
12191254 if (options .git_am_opts .argc ) {
12201255 /* all am options except -q are compatible only with --am */
12211256 for (i = options .git_am_opts .argc - 1 ; i >= 0 ; i -- )
@@ -1241,7 +1276,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
12411276 options .flags |= REBASE_FORCE ;
12421277 }
12431278
1244- if (options .type == REBASE_PRESERVE_MERGES )
1279+ if (options .type == REBASE_PRESERVE_MERGES ) {
12451280 /*
12461281 * Note: incompatibility with --signoff handled in signoff block above
12471282 * Note: incompatibility with --interactive is just a strong warning;
@@ -1251,6 +1286,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
12511286 die (_ ("error: cannot combine '--preserve-merges' with "
12521287 "'--rebase-merges'" ));
12531288
1289+ if (options .reschedule_failed_exec )
1290+ die (_ ("error: cannot combine '--preserve-merges' with "
1291+ "'--reschedule-failed-exec'" ));
1292+ }
1293+
12541294 if (options .rebase_merges ) {
12551295 if (strategy_options .nr )
12561296 die (_ ("error: cannot combine '--rebase-merges' with "
0 commit comments