The bugfix command works like the previous git bisect start --reverse. It switch the meaning of good(s) and bad from the default regression search approach to the bugfix one. I don't like adding more new subcommands into bisect, so I decided to not add ideas I have found on this mailinglist, like 'git bisect regression' or 'yes', 'no', 'fixed', 'unfixed' or whatever. The git bisect start/bugfix good/bad/skip log replay and vizualize were tested (however on simple linear example). The missing points: * git-bisect--helper has the "bad" hardcoded, so the commit fixing a bug is reffered as a bad one * in git bisect vizualize, the good commit is shown under refs/bad in gitk (however that's the same problem if user reverse the usage of good/bad itself). * documentation and tests of course Regards Michal Vyskocil --- bisect.c | 2 +- git-bisect.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/bisect.c b/bisect.c index c7b7d79..2eb34db 100644 --- a/bisect.c +++ b/bisect.c @@ -768,7 +768,7 @@ static void handle_bad_merge_base(void) fprintf(stderr, "Some good revs are not ancestor of the bad rev.\n" "git bisect cannot work properly in this case.\n" - "Maybe you mistake good and bad revs?\n"); + "Try git bisect bugfix to switch the default bisect logic.\n"); exit(1); } diff --git a/git-bisect.sh b/git-bisect.sh index 2524060..6959cf8 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -4,7 +4,9 @@ USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]' LONG_USAGE='git bisect help print this long help message. git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...] - reset bisect state and start bisection. + reset bisect state and start bisection to find a regression. +git bisect bugfix [--no-checkout] [<good> [<bad>...]] [--] [<pathspec>...] + reset bisect state and start bisection to find a bugfix. git bisect bad [<rev>] mark <rev> a known-bad revision. git bisect good [<rev>...] @@ -33,6 +35,29 @@ OPTIONS_SPEC= _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" +setup_bugfix_mode() { + /bin/touch "$GIT_DIR/BISECT_BUGFIX" +} + +bisect_bugfix_mode() { + test -f "$GIT_DIR/BISECT_BUGFIX" +} + +bisect_check_state() { + + if bisect_bugfix_mode; then + if test "$1" = "good"; then + echo "bad" + return 0 + elif test "$1" = "bad"; then + echo "good" + return 0 + fi + fi + + echo $1 +} + bisect_head() { if test -f "$GIT_DIR/BISECT_HEAD" @@ -69,6 +94,15 @@ bisect_start() { # Check for one bad and then some good revisions. # has_double_dash=0 + # + # Exchange the internal meaning of good/bad allowing bisect to find + # a commit fixing a bug, not "only" the one causes a regression + # + cmd="start" + if test -n "$1" && test "$1" = "bugfix"; then + cmd="bugfix" + shift 1 + fi for arg; do case "$arg" in --) has_double_dash=1; break ;; esac done @@ -99,10 +133,17 @@ bisect_start() { 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 + #if test $cmd = "bisect"; then + case $bad_seen in + 0) state='bad' ; bad_seen=1 ;; + *) state='good' ;; + esac + #else + # case $bad_seen in + # 0) state='good' ; bad_seen=1 ;; + # *) state='bad' ;; + # esac + #fi eval="$eval bisect_write '$state' '$rev' 'nolog' &&" shift ;; @@ -169,7 +210,10 @@ bisect_start() { } && git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" && eval "$eval true" && - echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit + echo "git bisect $cmd$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit + if test $cmd = "bugfix"; then + setup_bugfix_mode || exit + fi # # Check if we can proceed to the next bisect state. # @@ -225,7 +269,7 @@ bisect_skip() { bisect_state() { bisect_autostart - state=$1 + state=$(bisect_check_state $1) case "$#,$state" in 0,*) die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;; @@ -377,6 +421,7 @@ bisect_clean_state() { rm -f "$GIT_DIR/BISECT_LOG" && rm -f "$GIT_DIR/BISECT_NAMES" && rm -f "$GIT_DIR/BISECT_RUN" && + rm -f "$GIT_DIR/BISECT_BUGFIX" && # Cleanup head-name if it got left by an old version of git-bisect rm -f "$GIT_DIR/head-name" && git update-ref -d --no-deref BISECT_HEAD && @@ -401,7 +446,12 @@ bisect_replay () { start) cmd="bisect_start $rev" eval "$cmd" ;; + bugfix) + cmd="bisect_start 'bugfix' $rev" + setup_bugfix_mode || exit + eval "$cmd" ;; good|bad|skip) + command=$(bisect_check_state $1) bisect_write "$command" "$rev" ;; *) die "$(gettext "?? what are you talking about?")" ;; @@ -485,6 +535,8 @@ case "$#" in git bisect -h ;; start) bisect_start "$@" ;; + bugfix) + bisect_start "bugfix" "$@" ;; bad|good) bisect_state "$cmd" "$@" ;; skip) -- 1.7.6.3
Attachment:
pgpTEyzsomF4H.pgp
Description: PGP signature