@@ -24,11 +24,12 @@ static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
2424static GIT_PATH_FUNC (git_path_bisect_log , "BISECT_LOG ")
2525static GIT_PATH_FUNC (git_path_bisect_names , "BISECT_NAMES ")
2626static GIT_PATH_FUNC (git_path_bisect_first_parent , "BISECT_FIRST_PARENT ")
27+ static GIT_PATH_FUNC (git_path_bisect_auto_reset , "BISECT_AUTO_RESET ")
2728static GIT_PATH_FUNC (git_path_bisect_run , "BISECT_RUN ")
2829
2930#define BUILTIN_GIT_BISECT_START_USAGE \
3031 N_ ("git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n" \
31- " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" )
32+ " [--no-checkout] [--first-parent] [--auto-reset[=<where>]] [ <bad> [<good>...]] [--] [<pathspec>...]" )
3233#define BUILTIN_GIT_BISECT_BAD_USAGE \
3334 N_("git bisect (bad|new|<term-new>) [<rev>]")
3435#define BUILTIN_GIT_BISECT_GOOD_USAGE \
@@ -48,7 +49,7 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
4849#define BUILTIN_GIT_BISECT_LOG_USAGE \
4950 "git bisect log"
5051#define BUILTIN_GIT_BISECT_RUN_USAGE \
51- N_("git bisect run <cmd> [<arg>...]")
52+ N_("git bisect run [--auto-reset[=<where>]] <cmd> [<arg>...]")
5253#define BUILTIN_GIT_BISECT_HELP_USAGE \
5354 "git bisect help"
5455
@@ -68,6 +69,12 @@ static const char * const git_bisect_usage[] = {
6869 NULL
6970};
7071
72+ enum auto_reset_mode {
73+ AUTO_RESET_NONE ,
74+ AUTO_RESET_ORIGINAL ,
75+ AUTO_RESET_FOUND ,
76+ };
77+
7178struct add_bisect_ref_data {
7279 struct rev_info * revs ;
7380 unsigned int object_flags ;
@@ -268,6 +275,59 @@ static int bisect_reset(const char *commit, int quiet)
268275 return bisect_clean_state ();
269276}
270277
278+ static int parse_auto_reset (const char * value , enum auto_reset_mode * mode )
279+ {
280+ if (!strcmp (value , "original" ))
281+ * mode = AUTO_RESET_ORIGINAL ;
282+ else if (!strcmp (value , "found" ))
283+ * mode = AUTO_RESET_FOUND ;
284+ else
285+ return error (_ ("invalid value for '--auto-reset': '%s'" ), value );
286+
287+ return 0 ;
288+ }
289+
290+ static const char * auto_reset_mode_name (enum auto_reset_mode mode )
291+ {
292+ switch (mode ) {
293+ case AUTO_RESET_ORIGINAL :
294+ return "original" ;
295+ case AUTO_RESET_FOUND :
296+ return "found" ;
297+ case AUTO_RESET_NONE :
298+ BUG ("no name for unset auto-reset mode" );
299+ }
300+ BUG ("unknown auto-reset mode %d" , mode );
301+ }
302+
303+ static int bisect_auto_reset (struct bisect_terms * terms )
304+ {
305+ struct strbuf value = STRBUF_INIT ;
306+ enum auto_reset_mode mode ;
307+ char * commit = NULL ;
308+ int res ;
309+
310+ if (strbuf_read_file (& value , git_path_bisect_auto_reset (), 0 ) < 0 ) {
311+ res = error_errno (_ ("could not read '%s'" ),
312+ git_path_bisect_auto_reset ());
313+ goto cleanup ;
314+ }
315+ strbuf_trim (& value );
316+ if (parse_auto_reset (value .buf , & mode )) {
317+ res = -1 ;
318+ goto cleanup ;
319+ }
320+
321+ if (mode == AUTO_RESET_FOUND )
322+ commit = xstrfmt ("refs/bisect/%s" , terms -> term_bad );
323+ res = bisect_reset (commit , 1 );
324+
325+ cleanup :
326+ free (commit );
327+ strbuf_release (& value );
328+ return res ;
329+ }
330+
271331static void log_commit (FILE * fp ,
272332 const char * fmt , const char * state ,
273333 struct commit * commit )
@@ -688,6 +748,8 @@ static enum bisect_error bisect_next(struct bisect_terms *terms, const char *pre
688748
689749 if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ) {
690750 res = bisect_successful (terms );
751+ if (!res && !is_empty_or_missing_file (git_path_bisect_auto_reset ()))
752+ res = bisect_auto_reset (terms );
691753 return res ? res : BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ;
692754 } else if (res == BISECT_ONLY_SKIPPED_LEFT ) {
693755 res = bisect_skipped_commits (terms );
@@ -711,6 +773,7 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
711773{
712774 int no_checkout = 0 ;
713775 int first_parent_only = 0 ;
776+ enum auto_reset_mode auto_reset = AUTO_RESET_NONE ;
714777 int i , has_double_dash = 0 , must_write_terms = 0 , bad_seen = 0 ;
715778 int flags , pathspec_pos ;
716779 enum bisect_error res = BISECT_OK ;
@@ -743,6 +806,13 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
743806 no_checkout = 1 ;
744807 } else if (!strcmp (arg , "--first-parent" )) {
745808 first_parent_only = 1 ;
809+ } else if (!strcmp (arg , "--auto-reset" )) {
810+ auto_reset = AUTO_RESET_ORIGINAL ;
811+ } else if (skip_prefix (arg , "--auto-reset=" , & arg )) {
812+ if (parse_auto_reset (arg , & auto_reset )) {
813+ res = BISECT_FAILED ;
814+ goto finish ;
815+ }
746816 } else if (!strcmp (arg , "--term-good" ) ||
747817 !strcmp (arg , "--term-old" )) {
748818 i ++ ;
@@ -780,6 +850,10 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
780850 break ;
781851 }
782852 }
853+ if (auto_reset != AUTO_RESET_NONE && no_checkout ) {
854+ res = error (_ ("'--auto-reset' cannot be used with '--no-checkout'" ));
855+ goto finish ;
856+ }
783857 pathspec_pos = i ;
784858
785859 /*
@@ -857,6 +931,10 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
857931 if (first_parent_only )
858932 write_file (git_path_bisect_first_parent (), "\n" );
859933
934+ if (auto_reset != AUTO_RESET_NONE )
935+ write_file (git_path_bisect_auto_reset (), "%s\n" ,
936+ auto_reset_mode_name (auto_reset ));
937+
860938 if (no_checkout ) {
861939 if (repo_get_oid (the_repository , start_head .buf , & oid ) < 0 ) {
862940 res = error (_ ("invalid ref: '%s'" ), start_head .buf );
@@ -1235,13 +1313,31 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
12351313{
12361314 int res = BISECT_OK ;
12371315 struct strbuf command = STRBUF_INIT ;
1316+ enum auto_reset_mode auto_reset = AUTO_RESET_NONE ;
1317+ const char * auto_reset_arg ;
12381318 const char * new_state ;
12391319 int temporary_stdout_fd , saved_stdout ;
12401320 int is_first_run = 1 ;
12411321
12421322 if (bisect_next_check (terms , NULL ))
12431323 return BISECT_FAILED ;
12441324
1325+ if (argc && !strcmp (argv [0 ], "--auto-reset" ))
1326+ auto_reset = AUTO_RESET_ORIGINAL ;
1327+ else if (argc && skip_prefix (argv [0 ], "--auto-reset=" , & auto_reset_arg )) {
1328+ if (parse_auto_reset (auto_reset_arg , & auto_reset ))
1329+ return BISECT_FAILED ;
1330+ }
1331+
1332+ if (auto_reset != AUTO_RESET_NONE ) {
1333+ if (refs_ref_exists (get_main_ref_store (the_repository ), "BISECT_HEAD" ))
1334+ return error (_ ("'--auto-reset' cannot be used with '--no-checkout'" ));
1335+ write_file (git_path_bisect_auto_reset (), "%s\n" ,
1336+ auto_reset_mode_name (auto_reset ));
1337+ argc -- ;
1338+ argv ++ ;
1339+ }
1340+
12451341 if (!argc ) {
12461342 error (_ ("bisect run failed: no command provided." ));
12471343 return BISECT_FAILED ;
0 commit comments