Skip to content

Commit da68bf3

Browse files
committed
Merge branch 'js/bisect-no-checkout'
* js/bisect-no-checkout: bisect: add support for bisecting bare repositories bisect: further style nitpicks bisect: replace "; then" with "\n<tab>*then" bisect: cleanup whitespace errors in git-bisect.sh. bisect: add documentation for --no-checkout option. bisect: add tests for the --no-checkout option. bisect: introduce --no-checkout support into porcelain. bisect: introduce support for --no-checkout option. bisect: add tests to document expected behaviour in presence of broken trees. bisect: use && to connect statements that are deferred with eval. bisect: move argument parsing before state modification.
2 parents ca01600 + 24c5128 commit da68bf3

File tree

7 files changed

+430
-178
lines changed

7 files changed

+430
-178
lines changed

Documentation/git-bisect.txt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ The command takes various subcommands, and different options depending
1717
on the subcommand:
1818

1919
git bisect help
20-
git bisect start [<bad> [<good>...]] [--] [<paths>...]
20+
git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
2121
git bisect bad [<rev>]
2222
git bisect good [<rev>...]
2323
git bisect skip [(<rev>|<range>)...]
@@ -263,6 +263,19 @@ rewind the tree to the pristine state. Finally the script should exit
263263
with the status of the real test to let the "git bisect run" command loop
264264
determine the eventual outcome of the bisect session.
265265

266+
OPTIONS
267+
-------
268+
--no-checkout::
269+
+
270+
Do not checkout the new working tree at each iteration of the bisection
271+
process. Instead just update a special reference named 'BISECT_HEAD' to make
272+
it point to the commit that should be tested.
273+
+
274+
This option may be useful when the test you would perform in each step
275+
does not require a checked out tree.
276+
+
277+
If the repository is bare, `--no-checkout` is assumed.
278+
266279
EXAMPLES
267280
--------
268281

@@ -343,6 +356,25 @@ $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
343356
This shows that you can do without a run script if you write the test
344357
on a single line.
345358

359+
* Locate a good region of the object graph in a damaged repository
360+
+
361+
------------
362+
$ git bisect start HEAD <known-good-commit> [ <boundary-commit> ... ] --no-checkout
363+
$ git bisect run sh -c '
364+
GOOD=$(git for-each-ref "--format=%(objectname)" refs/bisect/good-*) &&
365+
git rev-list --objects BISECT_HEAD --not $GOOD >tmp.$$ &&
366+
git pack-objects --stdout >/dev/null <tmp.$$
367+
rc=$?
368+
rm -f tmp.$$
369+
test $rc = 0'
370+
371+
------------
372+
+
373+
In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit that
374+
has at least one parent whose reachable graph is fully traversable in the sense
375+
required by 'git pack objects'.
376+
377+
346378
SEE ALSO
347379
--------
348380
link:git-bisect-lk2009.html[Fighting regressions with git bisect],

bisect.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct argv_array {
2424

2525
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
2626
static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
27+
static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
2728

2829
/* bits #0-15 in revision.h */
2930

@@ -707,16 +708,23 @@ static void mark_expected_rev(char *bisect_rev_hex)
707708
die("closing file %s: %s", filename, strerror(errno));
708709
}
709710

710-
static int bisect_checkout(char *bisect_rev_hex)
711+
static int bisect_checkout(char *bisect_rev_hex, int no_checkout)
711712
{
712713
int res;
713714

714715
mark_expected_rev(bisect_rev_hex);
715716

716717
argv_checkout[2] = bisect_rev_hex;
717-
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
718-
if (res)
719-
exit(res);
718+
if (no_checkout) {
719+
argv_update_ref[3] = bisect_rev_hex;
720+
if (run_command_v_opt(argv_update_ref, RUN_GIT_CMD))
721+
die("update-ref --no-deref HEAD failed on %s",
722+
bisect_rev_hex);
723+
} else {
724+
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
725+
if (res)
726+
exit(res);
727+
}
720728

721729
argv_show_branch[1] = bisect_rev_hex;
722730
return run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
@@ -788,7 +796,7 @@ static void handle_skipped_merge_base(const unsigned char *mb)
788796
* - If one is "skipped", we can't know but we should warn.
789797
* - If we don't know, we should check it out and ask the user to test.
790798
*/
791-
static void check_merge_bases(void)
799+
static void check_merge_bases(int no_checkout)
792800
{
793801
struct commit_list *result;
794802
int rev_nr;
@@ -806,7 +814,7 @@ static void check_merge_bases(void)
806814
handle_skipped_merge_base(mb);
807815
} else {
808816
printf("Bisecting: a merge base must be tested\n");
809-
exit(bisect_checkout(sha1_to_hex(mb)));
817+
exit(bisect_checkout(sha1_to_hex(mb), no_checkout));
810818
}
811819
}
812820

@@ -849,7 +857,7 @@ static int check_ancestors(const char *prefix)
849857
* If a merge base must be tested by the user, its source code will be
850858
* checked out to be tested by the user and we will exit.
851859
*/
852-
static void check_good_are_ancestors_of_bad(const char *prefix)
860+
static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
853861
{
854862
const char *filename = git_path("BISECT_ANCESTORS_OK");
855863
struct stat st;
@@ -868,7 +876,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
868876

869877
/* Check if all good revs are ancestor of the bad rev. */
870878
if (check_ancestors(prefix))
871-
check_merge_bases();
879+
check_merge_bases(no_checkout);
872880

873881
/* Create file BISECT_ANCESTORS_OK. */
874882
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
@@ -908,8 +916,11 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
908916
* We use the convention that exiting with an exit code 10 means that
909917
* the bisection process finished successfully.
910918
* In this case the calling shell script should exit 0.
919+
*
920+
* If no_checkout is non-zero, the bisection process does not
921+
* checkout the trial commit but instead simply updates BISECT_HEAD.
911922
*/
912-
int bisect_next_all(const char *prefix)
923+
int bisect_next_all(const char *prefix, int no_checkout)
913924
{
914925
struct rev_info revs;
915926
struct commit_list *tried;
@@ -920,7 +931,7 @@ int bisect_next_all(const char *prefix)
920931
if (read_bisect_refs())
921932
die("reading bisect refs failed");
922933

923-
check_good_are_ancestors_of_bad(prefix);
934+
check_good_are_ancestors_of_bad(prefix, no_checkout);
924935

925936
bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
926937
revs.limited = 1;
@@ -966,6 +977,6 @@ int bisect_next_all(const char *prefix)
966977
"(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
967978
steps, (steps == 1 ? "" : "s"));
968979

969-
return bisect_checkout(bisect_rev_hex);
980+
return bisect_checkout(bisect_rev_hex, no_checkout);
970981
}
971982

bisect.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct rev_list_info {
2727
const char *header_prefix;
2828
};
2929

30-
extern int bisect_next_all(const char *prefix);
30+
extern int bisect_next_all(const char *prefix, int no_checkout);
3131

3232
extern int estimate_bisect_steps(int all);
3333

builtin/bisect--helper.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44
#include "bisect.h"
55

66
static const char * const git_bisect_helper_usage[] = {
7-
"git bisect--helper --next-all",
7+
"git bisect--helper --next-all [--no-checkout]",
88
NULL
99
};
1010

1111
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1212
{
1313
int next_all = 0;
14+
int no_checkout = 0;
1415
struct option options[] = {
1516
OPT_BOOLEAN(0, "next-all", &next_all,
1617
"perform 'git bisect next'"),
18+
OPT_BOOLEAN(0, "no-checkout", &no_checkout,
19+
"update BISECT_HEAD instead of checking out the current commit"),
1720
OPT_END()
1821
};
1922

@@ -24,5 +27,5 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
2427
usage_with_options(git_bisect_helper_usage, options);
2528

2629
/* next-all */
27-
return bisect_next_all(prefix);
30+
return bisect_next_all(prefix, no_checkout);
2831
}

0 commit comments

Comments
 (0)