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.maint
commit
da68bf3376
|
@ -17,7 +17,7 @@ The command takes various subcommands, and different options depending
|
||||||
on the subcommand:
|
on the subcommand:
|
||||||
|
|
||||||
git bisect help
|
git bisect help
|
||||||
git bisect start [<bad> [<good>...]] [--] [<paths>...]
|
git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
|
||||||
git bisect bad [<rev>]
|
git bisect bad [<rev>]
|
||||||
git bisect good [<rev>...]
|
git bisect good [<rev>...]
|
||||||
git bisect skip [(<rev>|<range>)...]
|
git bisect skip [(<rev>|<range>)...]
|
||||||
|
@ -263,6 +263,19 @@ rewind the tree to the pristine state. Finally the script should exit
|
||||||
with the status of the real test to let the "git bisect run" command loop
|
with the status of the real test to let the "git bisect run" command loop
|
||||||
determine the eventual outcome of the bisect session.
|
determine the eventual outcome of the bisect session.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
--no-checkout::
|
||||||
|
+
|
||||||
|
Do not checkout the new working tree at each iteration of the bisection
|
||||||
|
process. Instead just update a special reference named 'BISECT_HEAD' to make
|
||||||
|
it point to the commit that should be tested.
|
||||||
|
+
|
||||||
|
This option may be useful when the test you would perform in each step
|
||||||
|
does not require a checked out tree.
|
||||||
|
+
|
||||||
|
If the repository is bare, `--no-checkout` is assumed.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -343,6 +356,25 @@ $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
|
||||||
This shows that you can do without a run script if you write the test
|
This shows that you can do without a run script if you write the test
|
||||||
on a single line.
|
on a single line.
|
||||||
|
|
||||||
|
* Locate a good region of the object graph in a damaged repository
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git bisect start HEAD <known-good-commit> [ <boundary-commit> ... ] --no-checkout
|
||||||
|
$ git bisect run sh -c '
|
||||||
|
GOOD=$(git for-each-ref "--format=%(objectname)" refs/bisect/good-*) &&
|
||||||
|
git rev-list --objects BISECT_HEAD --not $GOOD >tmp.$$ &&
|
||||||
|
git pack-objects --stdout >/dev/null <tmp.$$
|
||||||
|
rc=$?
|
||||||
|
rm -f tmp.$$
|
||||||
|
test $rc = 0'
|
||||||
|
|
||||||
|
------------
|
||||||
|
+
|
||||||
|
In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit that
|
||||||
|
has at least one parent whose reachable graph is fully traversable in the sense
|
||||||
|
required by 'git pack objects'.
|
||||||
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
link:git-bisect-lk2009.html[Fighting regressions with git bisect],
|
link:git-bisect-lk2009.html[Fighting regressions with git bisect],
|
||||||
|
|
33
bisect.c
33
bisect.c
|
@ -24,6 +24,7 @@ struct argv_array {
|
||||||
|
|
||||||
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
|
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
|
||||||
static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
|
static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
|
||||||
|
static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
|
||||||
|
|
||||||
/* bits #0-15 in revision.h */
|
/* bits #0-15 in revision.h */
|
||||||
|
|
||||||
|
@ -707,16 +708,23 @@ static void mark_expected_rev(char *bisect_rev_hex)
|
||||||
die("closing file %s: %s", filename, strerror(errno));
|
die("closing file %s: %s", filename, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bisect_checkout(char *bisect_rev_hex)
|
static int bisect_checkout(char *bisect_rev_hex, int no_checkout)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
mark_expected_rev(bisect_rev_hex);
|
mark_expected_rev(bisect_rev_hex);
|
||||||
|
|
||||||
argv_checkout[2] = bisect_rev_hex;
|
argv_checkout[2] = bisect_rev_hex;
|
||||||
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
|
if (no_checkout) {
|
||||||
if (res)
|
argv_update_ref[3] = bisect_rev_hex;
|
||||||
exit(res);
|
if (run_command_v_opt(argv_update_ref, RUN_GIT_CMD))
|
||||||
|
die("update-ref --no-deref HEAD failed on %s",
|
||||||
|
bisect_rev_hex);
|
||||||
|
} else {
|
||||||
|
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
|
||||||
|
if (res)
|
||||||
|
exit(res);
|
||||||
|
}
|
||||||
|
|
||||||
argv_show_branch[1] = bisect_rev_hex;
|
argv_show_branch[1] = bisect_rev_hex;
|
||||||
return run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
|
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)
|
||||||
* - If one is "skipped", we can't know but we should warn.
|
* - If one is "skipped", we can't know but we should warn.
|
||||||
* - If we don't know, we should check it out and ask the user to test.
|
* - If we don't know, we should check it out and ask the user to test.
|
||||||
*/
|
*/
|
||||||
static void check_merge_bases(void)
|
static void check_merge_bases(int no_checkout)
|
||||||
{
|
{
|
||||||
struct commit_list *result;
|
struct commit_list *result;
|
||||||
int rev_nr;
|
int rev_nr;
|
||||||
|
@ -806,7 +814,7 @@ static void check_merge_bases(void)
|
||||||
handle_skipped_merge_base(mb);
|
handle_skipped_merge_base(mb);
|
||||||
} else {
|
} else {
|
||||||
printf("Bisecting: a merge base must be tested\n");
|
printf("Bisecting: a merge base must be tested\n");
|
||||||
exit(bisect_checkout(sha1_to_hex(mb)));
|
exit(bisect_checkout(sha1_to_hex(mb), no_checkout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,7 +857,7 @@ static int check_ancestors(const char *prefix)
|
||||||
* If a merge base must be tested by the user, its source code will be
|
* If a merge base must be tested by the user, its source code will be
|
||||||
* checked out to be tested by the user and we will exit.
|
* checked out to be tested by the user and we will exit.
|
||||||
*/
|
*/
|
||||||
static void check_good_are_ancestors_of_bad(const char *prefix)
|
static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
|
||||||
{
|
{
|
||||||
const char *filename = git_path("BISECT_ANCESTORS_OK");
|
const char *filename = git_path("BISECT_ANCESTORS_OK");
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -868,7 +876,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
|
||||||
|
|
||||||
/* Check if all good revs are ancestor of the bad rev. */
|
/* Check if all good revs are ancestor of the bad rev. */
|
||||||
if (check_ancestors(prefix))
|
if (check_ancestors(prefix))
|
||||||
check_merge_bases();
|
check_merge_bases(no_checkout);
|
||||||
|
|
||||||
/* Create file BISECT_ANCESTORS_OK. */
|
/* Create file BISECT_ANCESTORS_OK. */
|
||||||
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
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)
|
||||||
* We use the convention that exiting with an exit code 10 means that
|
* We use the convention that exiting with an exit code 10 means that
|
||||||
* the bisection process finished successfully.
|
* the bisection process finished successfully.
|
||||||
* In this case the calling shell script should exit 0.
|
* In this case the calling shell script should exit 0.
|
||||||
|
*
|
||||||
|
* If no_checkout is non-zero, the bisection process does not
|
||||||
|
* checkout the trial commit but instead simply updates BISECT_HEAD.
|
||||||
*/
|
*/
|
||||||
int bisect_next_all(const char *prefix)
|
int bisect_next_all(const char *prefix, int no_checkout)
|
||||||
{
|
{
|
||||||
struct rev_info revs;
|
struct rev_info revs;
|
||||||
struct commit_list *tried;
|
struct commit_list *tried;
|
||||||
|
@ -920,7 +931,7 @@ int bisect_next_all(const char *prefix)
|
||||||
if (read_bisect_refs())
|
if (read_bisect_refs())
|
||||||
die("reading bisect refs failed");
|
die("reading bisect refs failed");
|
||||||
|
|
||||||
check_good_are_ancestors_of_bad(prefix);
|
check_good_are_ancestors_of_bad(prefix, no_checkout);
|
||||||
|
|
||||||
bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
|
bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
|
||||||
revs.limited = 1;
|
revs.limited = 1;
|
||||||
|
@ -966,6 +977,6 @@ int bisect_next_all(const char *prefix)
|
||||||
"(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
|
"(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
|
||||||
steps, (steps == 1 ? "" : "s"));
|
steps, (steps == 1 ? "" : "s"));
|
||||||
|
|
||||||
return bisect_checkout(bisect_rev_hex);
|
return bisect_checkout(bisect_rev_hex, no_checkout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
bisect.h
2
bisect.h
|
@ -27,7 +27,7 @@ struct rev_list_info {
|
||||||
const char *header_prefix;
|
const char *header_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int bisect_next_all(const char *prefix);
|
extern int bisect_next_all(const char *prefix, int no_checkout);
|
||||||
|
|
||||||
extern int estimate_bisect_steps(int all);
|
extern int estimate_bisect_steps(int all);
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,19 @@
|
||||||
#include "bisect.h"
|
#include "bisect.h"
|
||||||
|
|
||||||
static const char * const git_bisect_helper_usage[] = {
|
static const char * const git_bisect_helper_usage[] = {
|
||||||
"git bisect--helper --next-all",
|
"git bisect--helper --next-all [--no-checkout]",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int next_all = 0;
|
int next_all = 0;
|
||||||
|
int no_checkout = 0;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOLEAN(0, "next-all", &next_all,
|
OPT_BOOLEAN(0, "next-all", &next_all,
|
||||||
"perform 'git bisect next'"),
|
"perform 'git bisect next'"),
|
||||||
|
OPT_BOOLEAN(0, "no-checkout", &no_checkout,
|
||||||
|
"update BISECT_HEAD instead of checking out the current commit"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,5 +27,5 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
||||||
usage_with_options(git_bisect_helper_usage, options);
|
usage_with_options(git_bisect_helper_usage, options);
|
||||||
|
|
||||||
/* next-all */
|
/* next-all */
|
||||||
return bisect_next_all(prefix);
|
return bisect_next_all(prefix, no_checkout);
|
||||||
}
|
}
|
||||||
|
|
341
git-bisect.sh
341
git-bisect.sh
|
@ -2,38 +2,47 @@
|
||||||
|
|
||||||
USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
|
USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
|
||||||
LONG_USAGE='git bisect help
|
LONG_USAGE='git bisect help
|
||||||
print this long help message.
|
print this long help message.
|
||||||
git bisect start [<bad> [<good>...]] [--] [<pathspec>...]
|
git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
|
||||||
reset bisect state and start bisection.
|
reset bisect state and start bisection.
|
||||||
git bisect bad [<rev>]
|
git bisect bad [<rev>]
|
||||||
mark <rev> a known-bad revision.
|
mark <rev> a known-bad revision.
|
||||||
git bisect good [<rev>...]
|
git bisect good [<rev>...]
|
||||||
mark <rev>... known-good revisions.
|
mark <rev>... known-good revisions.
|
||||||
git bisect skip [(<rev>|<range>)...]
|
git bisect skip [(<rev>|<range>)...]
|
||||||
mark <rev>... untestable revisions.
|
mark <rev>... untestable revisions.
|
||||||
git bisect next
|
git bisect next
|
||||||
find next bisection to test and check it out.
|
find next bisection to test and check it out.
|
||||||
git bisect reset [<commit>]
|
git bisect reset [<commit>]
|
||||||
finish bisection search and go back to commit.
|
finish bisection search and go back to commit.
|
||||||
git bisect visualize
|
git bisect visualize
|
||||||
show bisect status in gitk.
|
show bisect status in gitk.
|
||||||
git bisect replay <logfile>
|
git bisect replay <logfile>
|
||||||
replay bisection log.
|
replay bisection log.
|
||||||
git bisect log
|
git bisect log
|
||||||
show bisect log.
|
show bisect log.
|
||||||
git bisect run <cmd>...
|
git bisect run <cmd>...
|
||||||
use <cmd>... to automatically bisect.
|
use <cmd>... to automatically bisect.
|
||||||
|
|
||||||
Please use "git help bisect" to get the full man page.'
|
Please use "git help bisect" to get the full man page.'
|
||||||
|
|
||||||
OPTIONS_SPEC=
|
OPTIONS_SPEC=
|
||||||
. git-sh-setup
|
. git-sh-setup
|
||||||
. git-sh-i18n
|
. git-sh-i18n
|
||||||
require_work_tree
|
|
||||||
|
|
||||||
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
|
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
|
||||||
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
|
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
|
||||||
|
|
||||||
|
bisect_head()
|
||||||
|
{
|
||||||
|
if test -f "$GIT_DIR/BISECT_HEAD"
|
||||||
|
then
|
||||||
|
echo BISECT_HEAD
|
||||||
|
else
|
||||||
|
echo HEAD
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
bisect_autostart() {
|
bisect_autostart() {
|
||||||
test -s "$GIT_DIR/BISECT_START" || {
|
test -s "$GIT_DIR/BISECT_START" || {
|
||||||
(
|
(
|
||||||
|
@ -45,7 +54,7 @@ bisect_autostart() {
|
||||||
# TRANSLATORS: Make sure to include [Y] and [n] in your
|
# TRANSLATORS: Make sure to include [Y] and [n] in your
|
||||||
# translation. The program will only accept English input
|
# translation. The program will only accept English input
|
||||||
# at this point.
|
# at this point.
|
||||||
gettext "Do you want me to do it for you [Y/n]? " >&2
|
gettext "Do you want me to do it for you [Y/n]? " >&2
|
||||||
read yesno
|
read yesno
|
||||||
case "$yesno" in
|
case "$yesno" in
|
||||||
[Nn]*)
|
[Nn]*)
|
||||||
|
@ -59,6 +68,50 @@ bisect_autostart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bisect_start() {
|
bisect_start() {
|
||||||
|
#
|
||||||
|
# Check for one bad and then some good revisions.
|
||||||
|
#
|
||||||
|
has_double_dash=0
|
||||||
|
for arg; do
|
||||||
|
case "$arg" in --) has_double_dash=1; break ;; esac
|
||||||
|
done
|
||||||
|
orig_args=$(git rev-parse --sq-quote "$@")
|
||||||
|
bad_seen=0
|
||||||
|
eval=''
|
||||||
|
if test "z$(git rev-parse --is-bare-repository)" != zfalse
|
||||||
|
then
|
||||||
|
mode=--no-checkout
|
||||||
|
else
|
||||||
|
mode=''
|
||||||
|
fi
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
arg="$1"
|
||||||
|
case "$arg" in
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--no-checkout)
|
||||||
|
mode=--no-checkout
|
||||||
|
shift ;;
|
||||||
|
--*)
|
||||||
|
die "$(eval_gettext "unrecognised option: '\$arg'")" ;;
|
||||||
|
*)
|
||||||
|
rev=$(git rev-parse -q --verify "$arg^{commit}") || {
|
||||||
|
test $has_double_dash -eq 1 &&
|
||||||
|
die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case $bad_seen in
|
||||||
|
0) state='bad' ; bad_seen=1 ;;
|
||||||
|
*) state='good' ;;
|
||||||
|
esac
|
||||||
|
eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
#
|
#
|
||||||
# Verify HEAD.
|
# Verify HEAD.
|
||||||
#
|
#
|
||||||
|
@ -74,7 +127,10 @@ bisect_start() {
|
||||||
then
|
then
|
||||||
# Reset to the rev from where we started.
|
# Reset to the rev from where we started.
|
||||||
start_head=$(cat "$GIT_DIR/BISECT_START")
|
start_head=$(cat "$GIT_DIR/BISECT_START")
|
||||||
git checkout "$start_head" -- || exit
|
if test "z$mode" != "z--no-checkout"
|
||||||
|
then
|
||||||
|
git checkout "$start_head" --
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# Get rev from where we start.
|
# Get rev from where we start.
|
||||||
case "$head" in
|
case "$head" in
|
||||||
|
@ -97,39 +153,6 @@ bisect_start() {
|
||||||
#
|
#
|
||||||
bisect_clean_state || exit
|
bisect_clean_state || exit
|
||||||
|
|
||||||
#
|
|
||||||
# Check for one bad and then some good revisions.
|
|
||||||
#
|
|
||||||
has_double_dash=0
|
|
||||||
for arg; do
|
|
||||||
case "$arg" in --) has_double_dash=1; break ;; esac
|
|
||||||
done
|
|
||||||
orig_args=$(git rev-parse --sq-quote "$@")
|
|
||||||
bad_seen=0
|
|
||||||
eval=''
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
arg="$1"
|
|
||||||
case "$arg" in
|
|
||||||
--)
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
rev=$(git rev-parse -q --verify "$arg^{commit}") || {
|
|
||||||
test $has_double_dash -eq 1 &&
|
|
||||||
die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case $bad_seen in
|
|
||||||
0) state='bad' ; bad_seen=1 ;;
|
|
||||||
*) state='good' ;;
|
|
||||||
esac
|
|
||||||
eval="$eval bisect_write '$state' '$rev' 'nolog'; "
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Change state.
|
# Change state.
|
||||||
# In case of mistaken revs or checkout error, or signals received,
|
# In case of mistaken revs or checkout error, or signals received,
|
||||||
|
@ -143,9 +166,12 @@ bisect_start() {
|
||||||
#
|
#
|
||||||
# Write new start state.
|
# Write new start state.
|
||||||
#
|
#
|
||||||
echo "$start_head" >"$GIT_DIR/BISECT_START" &&
|
echo "$start_head" >"$GIT_DIR/BISECT_START" && {
|
||||||
|
test "z$mode" != "z--no-checkout" ||
|
||||||
|
git update-ref --no-deref BISECT_HEAD "$start_head"
|
||||||
|
} &&
|
||||||
git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
|
git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
|
||||||
eval "$eval" &&
|
eval "$eval true" &&
|
||||||
echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
|
echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
|
||||||
#
|
#
|
||||||
# Check if we can proceed to the next bisect state.
|
# Check if we can proceed to the next bisect state.
|
||||||
|
@ -176,7 +202,8 @@ is_expected_rev() {
|
||||||
|
|
||||||
check_expected_revs() {
|
check_expected_revs() {
|
||||||
for _rev in "$@"; do
|
for _rev in "$@"; do
|
||||||
if ! is_expected_rev "$_rev"; then
|
if ! is_expected_rev "$_rev"
|
||||||
|
then
|
||||||
rm -f "$GIT_DIR/BISECT_ANCESTORS_OK"
|
rm -f "$GIT_DIR/BISECT_ANCESTORS_OK"
|
||||||
rm -f "$GIT_DIR/BISECT_EXPECTED_REV"
|
rm -f "$GIT_DIR/BISECT_EXPECTED_REV"
|
||||||
return
|
return
|
||||||
|
@ -185,18 +212,18 @@ check_expected_revs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bisect_skip() {
|
bisect_skip() {
|
||||||
all=''
|
all=''
|
||||||
for arg in "$@"
|
for arg in "$@"
|
||||||
do
|
do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
*..*)
|
*..*)
|
||||||
revs=$(git rev-list "$arg") || die "$(eval_gettext "Bad rev input: \$arg")" ;;
|
revs=$(git rev-list "$arg") || die "$(eval_gettext "Bad rev input: \$arg")" ;;
|
||||||
*)
|
*)
|
||||||
revs=$(git rev-parse --sq-quote "$arg") ;;
|
revs=$(git rev-parse --sq-quote "$arg") ;;
|
||||||
esac
|
esac
|
||||||
all="$all $revs"
|
all="$all $revs"
|
||||||
done
|
done
|
||||||
eval bisect_state 'skip' $all
|
eval bisect_state 'skip' $all
|
||||||
}
|
}
|
||||||
|
|
||||||
bisect_state() {
|
bisect_state() {
|
||||||
|
@ -206,8 +233,8 @@ bisect_state() {
|
||||||
0,*)
|
0,*)
|
||||||
die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
|
die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
|
||||||
1,bad|1,good|1,skip)
|
1,bad|1,good|1,skip)
|
||||||
rev=$(git rev-parse --verify HEAD) ||
|
rev=$(git rev-parse --verify $(bisect_head)) ||
|
||||||
die "$(gettext "Bad rev input: HEAD")"
|
die "$(gettext "Bad rev input: $(bisect_head)")"
|
||||||
bisect_write "$state" "$rev"
|
bisect_write "$state" "$rev"
|
||||||
check_expected_revs "$rev" ;;
|
check_expected_revs "$rev" ;;
|
||||||
2,bad|*,good|*,skip)
|
2,bad|*,good|*,skip)
|
||||||
|
@ -291,10 +318,10 @@ bisect_next() {
|
||||||
bisect_next_check good
|
bisect_next_check good
|
||||||
|
|
||||||
# Perform all bisection computation, display and checkout
|
# Perform all bisection computation, display and checkout
|
||||||
git bisect--helper --next-all
|
git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
|
||||||
res=$?
|
res=$?
|
||||||
|
|
||||||
# Check if we should exit because bisection is finished
|
# Check if we should exit because bisection is finished
|
||||||
test $res -eq 10 && exit 0
|
test $res -eq 10 && exit 0
|
||||||
|
|
||||||
# Check for an error in the bisection process
|
# Check for an error in the bisection process
|
||||||
|
@ -309,7 +336,8 @@ bisect_visualize() {
|
||||||
if test $# = 0
|
if test $# = 0
|
||||||
then
|
then
|
||||||
if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
|
if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
|
||||||
type gitk >/dev/null 2>&1; then
|
type gitk >/dev/null 2>&1
|
||||||
|
then
|
||||||
set gitk
|
set gitk
|
||||||
else
|
else
|
||||||
set git log
|
set git log
|
||||||
|
@ -333,19 +361,20 @@ bisect_reset() {
|
||||||
case "$#" in
|
case "$#" in
|
||||||
0) branch=$(cat "$GIT_DIR/BISECT_START") ;;
|
0) branch=$(cat "$GIT_DIR/BISECT_START") ;;
|
||||||
1) git rev-parse --quiet --verify "$1^{commit}" > /dev/null || {
|
1) git rev-parse --quiet --verify "$1^{commit}" > /dev/null || {
|
||||||
invalid="$1"
|
invalid="$1"
|
||||||
die "$(eval_gettext "'\$invalid' is not a valid commit")"
|
die "$(eval_gettext "'\$invalid' is not a valid commit")"
|
||||||
}
|
}
|
||||||
branch="$1" ;;
|
branch="$1" ;;
|
||||||
*)
|
*)
|
||||||
usage ;;
|
usage ;;
|
||||||
esac
|
esac
|
||||||
if git checkout "$branch" -- ; then
|
|
||||||
bisect_clean_state
|
if ! test -f "$GIT_DIR/BISECT_HEAD" && ! git checkout "$branch" --
|
||||||
else
|
then
|
||||||
die "$(eval_gettext "Could not check out original HEAD '\$branch'.
|
die "$(eval_gettext "Could not check out original HEAD '\$branch'.
|
||||||
Try 'git bisect reset <commit>'.")"
|
Try 'git bisect reset <commit>'.")"
|
||||||
fi
|
fi
|
||||||
|
bisect_clean_state
|
||||||
}
|
}
|
||||||
|
|
||||||
bisect_clean_state() {
|
bisect_clean_state() {
|
||||||
|
@ -362,7 +391,8 @@ bisect_clean_state() {
|
||||||
rm -f "$GIT_DIR/BISECT_RUN" &&
|
rm -f "$GIT_DIR/BISECT_RUN" &&
|
||||||
# Cleanup head-name if it got left by an old version of git-bisect
|
# Cleanup head-name if it got left by an old version of git-bisect
|
||||||
rm -f "$GIT_DIR/head-name" &&
|
rm -f "$GIT_DIR/head-name" &&
|
||||||
|
git update-ref -d --no-deref BISECT_HEAD &&
|
||||||
|
# clean up BISECT_START last
|
||||||
rm -f "$GIT_DIR/BISECT_START"
|
rm -f "$GIT_DIR/BISECT_START"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +404,8 @@ bisect_replay () {
|
||||||
while read git bisect command rev
|
while read git bisect command rev
|
||||||
do
|
do
|
||||||
test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
|
test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
|
||||||
if test "$git" = "git-bisect"; then
|
if test "$git" = "git-bisect"
|
||||||
|
then
|
||||||
rev="$command"
|
rev="$command"
|
||||||
command="$bisect"
|
command="$bisect"
|
||||||
fi
|
fi
|
||||||
|
@ -392,65 +423,71 @@ bisect_replay () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bisect_run () {
|
bisect_run () {
|
||||||
bisect_next_check fail
|
bisect_next_check fail
|
||||||
|
|
||||||
while true
|
while true
|
||||||
do
|
do
|
||||||
command="$@"
|
command="$@"
|
||||||
eval_gettext "running \$command"; echo
|
eval_gettext "running \$command"; echo
|
||||||
"$@"
|
"$@"
|
||||||
res=$?
|
res=$?
|
||||||
|
|
||||||
# Check for really bad run error.
|
# Check for really bad run error.
|
||||||
if [ $res -lt 0 -o $res -ge 128 ]; then
|
if [ $res -lt 0 -o $res -ge 128 ]
|
||||||
(
|
then
|
||||||
eval_gettext "bisect run failed:
|
(
|
||||||
|
eval_gettext "bisect run failed:
|
||||||
exit code \$res from '\$command' is < 0 or >= 128" &&
|
exit code \$res from '\$command' is < 0 or >= 128" &&
|
||||||
echo
|
echo
|
||||||
) >&2
|
) >&2
|
||||||
exit $res
|
exit $res
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Find current state depending on run success or failure.
|
# Find current state depending on run success or failure.
|
||||||
# A special exit code of 125 means cannot test.
|
# A special exit code of 125 means cannot test.
|
||||||
if [ $res -eq 125 ]; then
|
if [ $res -eq 125 ]
|
||||||
state='skip'
|
then
|
||||||
elif [ $res -gt 0 ]; then
|
state='skip'
|
||||||
state='bad'
|
elif [ $res -gt 0 ]
|
||||||
else
|
then
|
||||||
state='good'
|
state='bad'
|
||||||
fi
|
else
|
||||||
|
state='good'
|
||||||
|
fi
|
||||||
|
|
||||||
# We have to use a subshell because "bisect_state" can exit.
|
# We have to use a subshell because "bisect_state" can exit.
|
||||||
( bisect_state $state > "$GIT_DIR/BISECT_RUN" )
|
( bisect_state $state > "$GIT_DIR/BISECT_RUN" )
|
||||||
res=$?
|
res=$?
|
||||||
|
|
||||||
cat "$GIT_DIR/BISECT_RUN"
|
cat "$GIT_DIR/BISECT_RUN"
|
||||||
|
|
||||||
if sane_grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \
|
if sane_grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \
|
||||||
> /dev/null; then
|
> /dev/null
|
||||||
(
|
then
|
||||||
gettext "bisect run cannot continue any more" &&
|
(
|
||||||
echo
|
gettext "bisect run cannot continue any more" &&
|
||||||
) >&2
|
echo
|
||||||
exit $res
|
) >&2
|
||||||
fi
|
exit $res
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $res -ne 0 ]; then
|
if [ $res -ne 0 ]
|
||||||
(
|
then
|
||||||
eval_gettext "bisect run failed:
|
(
|
||||||
|
eval_gettext "bisect run failed:
|
||||||
'bisect_state \$state' exited with error code \$res" &&
|
'bisect_state \$state' exited with error code \$res" &&
|
||||||
echo
|
echo
|
||||||
) >&2
|
) >&2
|
||||||
exit $res
|
exit $res
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then
|
if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null
|
||||||
gettext "bisect run success"; echo
|
then
|
||||||
exit 0;
|
gettext "bisect run success"; echo
|
||||||
fi
|
exit 0;
|
||||||
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
bisect_log () {
|
bisect_log () {
|
||||||
|
@ -460,33 +497,33 @@ bisect_log () {
|
||||||
|
|
||||||
case "$#" in
|
case "$#" in
|
||||||
0)
|
0)
|
||||||
usage ;;
|
usage ;;
|
||||||
*)
|
*)
|
||||||
cmd="$1"
|
cmd="$1"
|
||||||
shift
|
shift
|
||||||
case "$cmd" in
|
case "$cmd" in
|
||||||
help)
|
help)
|
||||||
git bisect -h ;;
|
git bisect -h ;;
|
||||||
start)
|
start)
|
||||||
bisect_start "$@" ;;
|
bisect_start "$@" ;;
|
||||||
bad|good)
|
bad|good)
|
||||||
bisect_state "$cmd" "$@" ;;
|
bisect_state "$cmd" "$@" ;;
|
||||||
skip)
|
skip)
|
||||||
bisect_skip "$@" ;;
|
bisect_skip "$@" ;;
|
||||||
next)
|
next)
|
||||||
# Not sure we want "next" at the UI level anymore.
|
# Not sure we want "next" at the UI level anymore.
|
||||||
bisect_next "$@" ;;
|
bisect_next "$@" ;;
|
||||||
visualize|view)
|
visualize|view)
|
||||||
bisect_visualize "$@" ;;
|
bisect_visualize "$@" ;;
|
||||||
reset)
|
reset)
|
||||||
bisect_reset "$@" ;;
|
bisect_reset "$@" ;;
|
||||||
replay)
|
replay)
|
||||||
bisect_replay "$@" ;;
|
bisect_replay "$@" ;;
|
||||||
log)
|
log)
|
||||||
bisect_log ;;
|
bisect_log ;;
|
||||||
run)
|
run)
|
||||||
bisect_run "$@" ;;
|
bisect_run "$@" ;;
|
||||||
*)
|
*)
|
||||||
usage ;;
|
usage ;;
|
||||||
esac
|
esac
|
||||||
esac
|
esac
|
||||||
|
|
2
git.c
2
git.c
|
@ -334,7 +334,7 @@ static void handle_internal_command(int argc, const char **argv)
|
||||||
{ "annotate", cmd_annotate, RUN_SETUP },
|
{ "annotate", cmd_annotate, RUN_SETUP },
|
||||||
{ "apply", cmd_apply, RUN_SETUP_GENTLY },
|
{ "apply", cmd_apply, RUN_SETUP_GENTLY },
|
||||||
{ "archive", cmd_archive },
|
{ "archive", cmd_archive },
|
||||||
{ "bisect--helper", cmd_bisect__helper, RUN_SETUP | NEED_WORK_TREE },
|
{ "bisect--helper", cmd_bisect__helper, RUN_SETUP },
|
||||||
{ "blame", cmd_blame, RUN_SETUP },
|
{ "blame", cmd_blame, RUN_SETUP },
|
||||||
{ "branch", cmd_branch, RUN_SETUP },
|
{ "branch", cmd_branch, RUN_SETUP },
|
||||||
{ "bundle", cmd_bundle, RUN_SETUP_GENTLY },
|
{ "bundle", cmd_bundle, RUN_SETUP_GENTLY },
|
||||||
|
|
|
@ -126,6 +126,18 @@ test_expect_success 'bisect reset removes packed refs' '
|
||||||
test -z "$(git for-each-ref "refs/heads/bisect")"
|
test -z "$(git for-each-ref "refs/heads/bisect")"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect reset removes bisect state after --no-checkout' '
|
||||||
|
git bisect reset &&
|
||||||
|
git bisect start --no-checkout &&
|
||||||
|
git bisect good $HASH1 &&
|
||||||
|
git bisect bad $HASH3 &&
|
||||||
|
git bisect next &&
|
||||||
|
git bisect reset &&
|
||||||
|
test -z "$(git for-each-ref "refs/bisect/*")" &&
|
||||||
|
test -z "$(git for-each-ref "refs/heads/bisect")" &&
|
||||||
|
test -z "$(git for-each-ref "BISECT_HEAD")"
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'bisect start: back in good branch' '
|
test_expect_success 'bisect start: back in good branch' '
|
||||||
git branch > branch.output &&
|
git branch > branch.output &&
|
||||||
grep "* other" branch.output > /dev/null &&
|
grep "* other" branch.output > /dev/null &&
|
||||||
|
@ -138,15 +150,23 @@ test_expect_success 'bisect start: back in good branch' '
|
||||||
grep "* other" branch.output > /dev/null
|
grep "* other" branch.output > /dev/null
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'bisect start: no ".git/BISECT_START" if junk rev' '
|
test_expect_success 'bisect start: no ".git/BISECT_START" created if junk rev' '
|
||||||
git bisect start $HASH4 $HASH1 -- &&
|
git bisect reset &&
|
||||||
git bisect good &&
|
|
||||||
test_must_fail git bisect start $HASH4 foo -- &&
|
test_must_fail git bisect start $HASH4 foo -- &&
|
||||||
git branch > branch.output &&
|
git branch > branch.output &&
|
||||||
grep "* other" branch.output > /dev/null &&
|
grep "* other" branch.output > /dev/null &&
|
||||||
test_must_fail test -e .git/BISECT_START
|
test_must_fail test -e .git/BISECT_START
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if junk rev' '
|
||||||
|
git bisect start $HASH4 $HASH1 -- &&
|
||||||
|
git bisect good &&
|
||||||
|
cp .git/BISECT_START saved &&
|
||||||
|
test_must_fail git bisect start $HASH4 foo -- &&
|
||||||
|
git branch > branch.output &&
|
||||||
|
grep "* (no branch)" branch.output > /dev/null &&
|
||||||
|
test_cmp saved .git/BISECT_START
|
||||||
|
'
|
||||||
test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
|
test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
|
||||||
git bisect start $HASH4 $HASH1 -- &&
|
git bisect start $HASH4 $HASH1 -- &&
|
||||||
git bisect good &&
|
git bisect good &&
|
||||||
|
@ -572,6 +592,155 @@ test_expect_success 'erroring out when using bad path parameters' '
|
||||||
grep "bad path parameters" error.txt
|
grep "bad path parameters" error.txt
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'test bisection on bare repo - --no-checkout specified' '
|
||||||
|
git clone --bare . bare.nocheckout &&
|
||||||
|
(
|
||||||
|
cd bare.nocheckout &&
|
||||||
|
git bisect start --no-checkout &&
|
||||||
|
git bisect good $HASH1 &&
|
||||||
|
git bisect bad $HASH4 &&
|
||||||
|
git bisect run eval \
|
||||||
|
"test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
|
||||||
|
>../nocheckout.log &&
|
||||||
|
git bisect reset
|
||||||
|
) &&
|
||||||
|
grep "$HASH3 is the first bad commit" nocheckout.log
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'test bisection on bare repo - --no-checkout defaulted' '
|
||||||
|
git clone --bare . bare.defaulted &&
|
||||||
|
(
|
||||||
|
cd bare.defaulted &&
|
||||||
|
git bisect start &&
|
||||||
|
git bisect good $HASH1 &&
|
||||||
|
git bisect bad $HASH4 &&
|
||||||
|
git bisect run eval \
|
||||||
|
"test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
|
||||||
|
>../defaulted.log &&
|
||||||
|
git bisect reset
|
||||||
|
) &&
|
||||||
|
grep "$HASH3 is the first bad commit" defaulted.log
|
||||||
|
'
|
||||||
|
|
||||||
#
|
#
|
||||||
|
# This creates a broken branch which cannot be checked out because
|
||||||
|
# the tree created has been deleted.
|
||||||
#
|
#
|
||||||
|
# H1-H2-H3-H4-H5-H6-H7 <--other
|
||||||
|
# \
|
||||||
|
# S5-S6'-S7'-S8'-S9 <--broken
|
||||||
|
#
|
||||||
|
# Commits marked with ' have a missing tree.
|
||||||
|
#
|
||||||
|
test_expect_success 'broken branch creation' '
|
||||||
|
git bisect reset &&
|
||||||
|
git checkout -b broken $HASH4 &&
|
||||||
|
git tag BROKEN_HASH4 $HASH4 &&
|
||||||
|
add_line_into_file "5(broken): first line on a broken branch" hello2 &&
|
||||||
|
git tag BROKEN_HASH5 &&
|
||||||
|
mkdir missing &&
|
||||||
|
:> missing/MISSING &&
|
||||||
|
git add missing/MISSING &&
|
||||||
|
git commit -m "6(broken): Added file that will be deleted"
|
||||||
|
git tag BROKEN_HASH6 &&
|
||||||
|
add_line_into_file "7(broken): second line on a broken branch" hello2 &&
|
||||||
|
git tag BROKEN_HASH7 &&
|
||||||
|
add_line_into_file "8(broken): third line on a broken branch" hello2 &&
|
||||||
|
git tag BROKEN_HASH8 &&
|
||||||
|
git rm missing/MISSING &&
|
||||||
|
git commit -m "9(broken): Remove missing file"
|
||||||
|
git tag BROKEN_HASH9 &&
|
||||||
|
rm .git/objects/39/f7e61a724187ab767d2e08442d9b6b9dab587d
|
||||||
|
'
|
||||||
|
|
||||||
|
echo "" > expected.ok
|
||||||
|
cat > expected.missing-tree.default <<EOF
|
||||||
|
fatal: unable to read tree 39f7e61a724187ab767d2e08442d9b6b9dab587d
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'bisect fails if tree is broken on start commit' '
|
||||||
|
git bisect reset &&
|
||||||
|
test_must_fail git bisect start BROKEN_HASH7 BROKEN_HASH4 2>error.txt &&
|
||||||
|
test_cmp expected.missing-tree.default error.txt
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect fails if tree is broken on trial commit' '
|
||||||
|
git bisect reset &&
|
||||||
|
test_must_fail git bisect start BROKEN_HASH9 BROKEN_HASH4 2>error.txt &&
|
||||||
|
git reset --hard broken &&
|
||||||
|
git checkout broken &&
|
||||||
|
test_cmp expected.missing-tree.default error.txt
|
||||||
|
'
|
||||||
|
|
||||||
|
check_same()
|
||||||
|
{
|
||||||
|
echo "Checking $1 is the same as $2" &&
|
||||||
|
git rev-parse "$1" > expected.same &&
|
||||||
|
git rev-parse "$2" > expected.actual &&
|
||||||
|
test_cmp expected.same expected.actual
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 'bisect: --no-checkout - start commit bad' '
|
||||||
|
git bisect reset &&
|
||||||
|
git bisect start BROKEN_HASH7 BROKEN_HASH4 --no-checkout &&
|
||||||
|
check_same BROKEN_HASH6 BISECT_HEAD &&
|
||||||
|
git bisect reset
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect: --no-checkout - trial commit bad' '
|
||||||
|
git bisect reset &&
|
||||||
|
git bisect start broken BROKEN_HASH4 --no-checkout &&
|
||||||
|
check_same BROKEN_HASH6 BISECT_HEAD &&
|
||||||
|
git bisect reset
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect: --no-checkout - target before breakage' '
|
||||||
|
git bisect reset &&
|
||||||
|
git bisect start broken BROKEN_HASH4 --no-checkout &&
|
||||||
|
check_same BROKEN_HASH6 BISECT_HEAD &&
|
||||||
|
git bisect bad BISECT_HEAD &&
|
||||||
|
check_same BROKEN_HASH5 BISECT_HEAD &&
|
||||||
|
git bisect bad BISECT_HEAD &&
|
||||||
|
check_same BROKEN_HASH5 bisect/bad &&
|
||||||
|
git bisect reset
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect: --no-checkout - target in breakage' '
|
||||||
|
git bisect reset &&
|
||||||
|
git bisect start broken BROKEN_HASH4 --no-checkout &&
|
||||||
|
check_same BROKEN_HASH6 BISECT_HEAD &&
|
||||||
|
git bisect bad BISECT_HEAD &&
|
||||||
|
check_same BROKEN_HASH5 BISECT_HEAD &&
|
||||||
|
git bisect good BISECT_HEAD &&
|
||||||
|
check_same BROKEN_HASH6 bisect/bad &&
|
||||||
|
git bisect reset
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect: --no-checkout - target after breakage' '
|
||||||
|
git bisect reset &&
|
||||||
|
git bisect start broken BROKEN_HASH4 --no-checkout &&
|
||||||
|
check_same BROKEN_HASH6 BISECT_HEAD &&
|
||||||
|
git bisect good BISECT_HEAD &&
|
||||||
|
check_same BROKEN_HASH8 BISECT_HEAD &&
|
||||||
|
git bisect good BISECT_HEAD &&
|
||||||
|
check_same BROKEN_HASH9 bisect/bad &&
|
||||||
|
git bisect reset
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'bisect: demonstrate identification of damage boundary' "
|
||||||
|
git bisect reset &&
|
||||||
|
git checkout broken &&
|
||||||
|
git bisect start broken master --no-checkout &&
|
||||||
|
git bisect run sh -c '
|
||||||
|
GOOD=\$(git for-each-ref \"--format=%(objectname)\" refs/bisect/good-*) &&
|
||||||
|
git rev-list --objects BISECT_HEAD --not \$GOOD >tmp.\$\$ &&
|
||||||
|
git pack-objects --stdout >/dev/null < tmp.\$\$
|
||||||
|
rc=\$?
|
||||||
|
rm -f tmp.\$\$
|
||||||
|
test \$rc = 0' &&
|
||||||
|
check_same BROKEN_HASH6 bisect/bad &&
|
||||||
|
git bisect reset
|
||||||
|
"
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
Loading…
Reference in New Issue