Commit 0871984d authored by Christian Couder's avatar Christian Couder Committed by Junio C Hamano

bisect: make "git bisect" use new "--next-all" bisect-helper function

This patch replace the "--next-exit" option of "git bisect--helper"
with a "--next-all" option that does merge base checking using
the "check_good_are_ancestors_of_bad" function implemented in
"bisect.c" in a former patch.

The new "--next-all" option is then used in "" instead
of the "--next-exit" option, and all the shell functions in
"" that are now unused are removed.
Signed-off-by: Christian Couder's avatarChristian Couder <[email protected]>
Signed-off-by: default avatarJunio C Hamano <[email protected]>
parent d937d4ac
......@@ -830,7 +830,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
* the bisection process finished successfully.
* In this case the calling shell script should exit 0.
int bisect_next_exit(const char *prefix)
int bisect_next_all(const char *prefix)
struct rev_info revs;
struct commit_list *tried;
......@@ -841,6 +841,8 @@ int bisect_next_exit(const char *prefix)
if (read_bisect_refs())
die("reading bisect refs failed");
bisect_rev_setup(&revs, prefix);
bisect_common(&revs, &reaches, &all);
......@@ -27,7 +27,7 @@ struct rev_list_info {
extern int show_bisect_vars(struct rev_list_info *info, int reaches, int all);
extern int bisect_next_exit(const char *prefix);
extern int bisect_next_all(const char *prefix);
extern int estimate_bisect_steps(int all);
......@@ -4,24 +4,24 @@
#include "bisect.h"
static const char * const git_bisect_helper_usage[] = {
"git bisect--helper --next-exit",
"git bisect--helper --next-all",
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
int next_exit = 0;
int next_all = 0;
struct option options[] = {
OPT_BOOLEAN(0, "next-exit", &next_exit,
"output bisect result and exit instuctions"),
OPT_BOOLEAN(0, "next-all", &next_all,
"perform 'git bisect next'"),
argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
if (!next_exit)
if (!next_all)
usage_with_options(git_bisect_helper_usage, options);
/* next-exit */
return bisect_next_exit(prefix);
/* next-all */
return bisect_next_all(prefix);
......@@ -167,10 +167,6 @@ is_expected_rev() {
test "$1" = $(cat "$GIT_DIR/BISECT_EXPECTED_REV")
mark_expected_rev() {
check_expected_revs() {
for _rev in "[email protected]"; do
if ! is_expected_rev "$_rev"; then
......@@ -269,132 +265,13 @@ bisect_auto_next() {
bisect_next_check && bisect_next || :
bisect_checkout() {
echo "Bisecting: $_msg"
mark_expected_rev "$_rev"
git checkout -q "$_rev" -- || exit
git show-branch "$_rev"
is_among() {
case "$_list" in *$_rev*) return 0 ;; esac
return 1
handle_bad_merge_base() {
if is_expected_rev "$_badmb"; then
cat >&2 <<EOF
The merge base $_badmb is bad.
This means the bug has been fixed between $_badmb and [$_good].
exit 3
cat >&2 <<EOF
Some good revs are not ancestor of the bad rev.
git bisect cannot work properly in this case.
Maybe you mistake good and bad revs?
exit 1
handle_skipped_merge_base() {
cat >&2 <<EOF
Warning: the merge base between $_bad and [$_good] must be skipped.
So we cannot be sure the first bad commit is between $_mb and $_bad.
We continue anyway.
# "check_merge_bases" checks that merge bases are not "bad".
# - If one is "good", that's good, we have nothing to do.
# - If one is "bad", it means the user assumed something wrong
# and we must exit.
# - 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.
# In the last case we will return 1, and otherwise 0.
check_merge_bases() {
for _mb in $(git merge-base --all $_bad $_good)
if is_among "$_mb" "$_good"; then
elif test "$_mb" = "$_bad"; then
handle_bad_merge_base "$_bad" "$_good"
elif is_among "$_mb" "$_skip"; then
handle_skipped_merge_base "$_mb" "$_bad" "$_good"
bisect_checkout "$_mb" "a merge base must be tested"
return 1
return 0
# "check_good_are_ancestors_of_bad" checks that all "good" revs are
# ancestor of the "bad" rev.
# If that's not the case, we need to check the merge bases.
# If a merge base must be tested by the user we return 1 and
# otherwise 0.
check_good_are_ancestors_of_bad() {
_good=$(echo $2 | sed -e 's/\^//g')
# Bisecting with no good rev is ok
test -z "$_good" && return
_side=$(git rev-list $_good ^$_bad)
if test -n "$_side"; then
# Return if a checkout was done
check_merge_bases "$_bad" "$_good" "$_skip" || return
return 0
bisect_next() {
case "$#" in 0) ;; *) usage ;; esac
bisect_next_check good
# Get bad, good and skipped revs
bad=$(git rev-parse --verify refs/bisect/bad) &&
good=$(git for-each-ref --format='^%(objectname)' \
"refs/bisect/good-*" | tr '\012' ' ') &&
skip=$(git for-each-ref --format='%(objectname)' \
"refs/bisect/skip-*" | tr '\012' ' ') || exit
# Maybe some merge bases must be tested first
check_good_are_ancestors_of_bad "$bad" "$good" "$skip"
# Return now if a checkout has already been done
test "$?" -eq "1" && return
# Perform bisection computation, display and checkout
git bisect--helper --next-exit
# Perform all bisection computation, display and checkout
git bisect--helper --next-all
# Check if we should exit because bisection is finished
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment