Commit 21e5cfd8 authored by Antoine Delaite's avatar Antoine Delaite Committed by Junio C Hamano

bisect: add the terms old/new

When not looking for a regression during a bisect but for a fix or a
change in another given property, it can be confusing to use 'good'
and 'bad'.

This patch introduce `git bisect new` and `git bisect old` as an
alternative to 'bad' and good': the commits which have a certain
property must be marked as `new` and the ones which do not as `old`.

The output will be the first commit after the change in the property.
During a new/old bisect session you cannot use bad/good commands and
vice-versa.

Some commands are still not available for old/new:
     * git rev-list --bisect does not treat the revs/bisect/new and
       revs/bisect/old-SHA1 files.

Old discussions:
	- http://thread.gmane.org/gmane.comp.version-control.git/86063
		introduced bisect fix unfixed to find fix.
	- http://thread.gmane.org/gmane.comp.version-control.git/182398
		discussion around bisect yes/no or old/new.
	- http://thread.gmane.org/gmane.comp.version-control.git/199758
		last discussion and reviews
New discussions:
	- http://thread.gmane.org/gmane.comp.version-control.git/271320
		( v2 1/7-4/7 )
	- http://comments.gmane.org/gmane.comp.version-control.git/271343
		( v2 5/7-7/7 )
Signed-off-by: default avatarAntoine Delaite <[email protected]>
Signed-off-by: default avatarLouis Stuber <[email protected]>
Signed-off-by: default avatarValentin Duperray <[email protected]>
Signed-off-by: default avatarFranck Jonas <[email protected]>
Signed-off-by: default avatarLucien Kong <[email protected]>
Signed-off-by: default avatarThomas Nguy <[email protected]>
Signed-off-by: default avatarHuynh Khoi Nguyen Nguyen <[email protected]>
Signed-off-by: default avatarMatthieu Moy <[email protected]>
Signed-off-by: default avatarJunio C Hamano <[email protected]>
parent fe67687b
......@@ -17,8 +17,8 @@ The command takes various subcommands, and different options depending
on the subcommand:
git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
git bisect bad [<rev>]
git bisect good [<rev>...]
git bisect (bad|new) [<rev>]
git bisect (good|old) [<rev>...]
git bisect skip [(<rev>|<range>)...]
git bisect reset [<commit>]
git bisect visualize
......@@ -36,6 +36,13 @@ whether the selected commit is "good" or "bad". It continues narrowing
down the range until it finds the exact commit that introduced the
change.
In fact, `git bisect` can be used to find the commit that changed
*any* property of your project; e.g., the commit that fixed a bug, or
the commit that caused a benchmark's performance to improve. To
support this more general usage, the terms "old" and "new" can be used
in place of "good" and "bad". See
section "Alternate terms" below for more information.
Basic bisect commands: start, bad, good
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -111,6 +118,45 @@ bad revision, while `git bisect reset HEAD` will leave you on the
current bisection commit and avoid switching commits at all.
Alternate terms
~~~~~~~~~~~~~~~
Sometimes you are not looking for the commit that introduced a
breakage, but rather for a commit that caused a change between some
other "old" state and "new" state. For example, you might be looking
for the commit that introduced a particular fix. Or you might be
looking for the first commit in which the source-code filenames were
finally all converted to your company's naming standard. Or whatever.
In such cases it can be very confusing to use the terms "good" and
"bad" to refer to "the state before the change" and "the state after
the change". So instead, you can use the terms "old" and "new",
respectively, in place of "good" and "bad". (But note that you cannot
mix "good" and "bad" with "old" and "new" in a single session.)
In this more general usage, you provide `git bisect` with a "new"
commit has some property and an "old" commit that doesn't have that
property. Each time `git bisect` checks out a commit, you test if that
commit has the property. If it does, mark the commit as "new";
otherwise, mark it as "old". When the bisection is done, `git bisect`
will report which commit introduced the property.
To use "old" and "new" instead of "good" and bad, you must run `git
bisect start` without commits as argument and then run the following
commands to add the commits:
------------------------------------------------
git bisect old [<rev>]
------------------------------------------------
to indicate that a commit was before the sought change, or
------------------------------------------------
git bisect new [<rev>...]
------------------------------------------------
to indicate that it was after.
Bisect visualize
~~~~~~~~~~~~~~~~
......@@ -387,6 +433,14 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit
has at least one parent whose reachable graph is fully traversable in the sense
required by 'git pack objects'.
* Look for a fix instead of a regression in the code
+
------------
$ git bisect start
$ git bisect new HEAD # current commit is marked as new
$ git bisect old HEAD~10 # the tenth commit from now is marked as old
------------
Getting help
~~~~~~~~~~~~
......
......@@ -746,6 +746,11 @@ static void handle_bad_merge_base(void)
"This means the bug has been fixed "
"between %s and [%s].\n",
bad_hex, bad_hex, good_hex);
} else if (!strcmp(term_bad, "new") && !strcmp(term_good, "old")) {
fprintf(stderr, "The merge base %s is new.\n"
"The property has changed "
"between %s and [%s].\n",
bad_hex, bad_hex, good_hex);
} else {
fprintf(stderr, "The merge base %s is %s.\n"
"This means the first '%s' commit is "
......@@ -778,11 +783,11 @@ static void handle_skipped_merge_base(const unsigned char *mb)
}
/*
* "check_merge_bases" checks that merge bases are not "bad".
* "check_merge_bases" checks that merge bases are not "bad" (or "new").
*
* - If one is "bad", it means the user assumed something wrong
* - If one is "bad" (or "new"), it means the user assumed something wrong
* and we must exit with a non 0 error code.
* - If one is "good", that's good, we have nothing to do.
* - If one is "good" (or "old"), that's good, we have nothing to do.
* - 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.
*/
......
#!/bin/sh
USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
USAGE='[help|start|bad|good|new|old|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.
git bisect bad [<rev>]
mark <rev> a known-bad revision.
git bisect good [<rev>...]
mark <rev>... known-good revisions.
git bisect (bad|new) [<rev>]
mark <rev> a known-bad revision/
a revision after change in a given property.
git bisect (good|old) [<rev>...]
mark <rev>... known-good revisions/
revisions before change in a given property.
git bisect skip [(<rev>|<range>)...]
mark <rev>... untestable revisions.
git bisect next
......@@ -294,7 +296,7 @@ bisect_next_check() {
false
;;
t,,"$TERM_GOOD")
# have bad but not good. we could bisect although
# have bad (or new) but not good (or old). we could bisect although
# this is less optimum.
eval_gettextln "Warning: bisecting only with a \$TERM_BAD commit." >&2
if test -t 0
......@@ -587,14 +589,20 @@ check_and_set_terms () {
write_terms bad good
fi
;;
new|old)
if ! test -s "$GIT_DIR/BISECT_TERMS"
then
write_terms new old
fi
;;
esac ;;
esac
}
bisect_voc () {
case "$1" in
bad) echo "bad" ;;
good) echo "good" ;;
bad) echo "bad|new" ;;
good) echo "good|old" ;;
esac
}
......@@ -610,7 +618,7 @@ case "$#" in
git bisect -h ;;
start)
bisect_start "[email protected]" ;;
bad|good|"$TERM_BAD"|"$TERM_GOOD")
bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
bisect_state "$cmd" "[email protected]" ;;
skip)
bisect_skip "[email protected]" ;;
......
......@@ -759,4 +759,42 @@ test_expect_success '"git bisect bad HEAD" behaves as "git bisect bad"' '
git bisect reset
'
test_expect_success 'bisect starts with only one new' '
git bisect reset &&
git bisect start &&
git bisect new $HASH4 &&
git bisect next
'
test_expect_success 'bisect does not start with only one old' '
git bisect reset &&
git bisect start &&
git bisect old $HASH1 &&
test_must_fail git bisect next
'
test_expect_success 'bisect start with one new and old' '
git bisect reset &&
git bisect start &&
git bisect old $HASH1 &&
git bisect new $HASH4 &&
git bisect new &&
git bisect new >bisect_result &&
grep "$HASH2 is the first new commit" bisect_result &&
git bisect log >log_to_replay.txt &&
git bisect reset
'
test_expect_success 'bisect replay with old and new' '
git bisect replay log_to_replay.txt >bisect_result &&
grep "$HASH2 is the first new commit" bisect_result &&
git bisect reset
'
test_expect_success 'bisect cannot mix old/new and good/bad' '
git bisect start &&
git bisect bad $HASH4 &&
test_must_fail git bisect old $HASH1
'
test_done
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment