Skip to content

Commit 21e5cfd

Browse files
CanardChouChinoisgitster
authored andcommitted
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: Antoine Delaite <[email protected]> Signed-off-by: Louis Stuber <[email protected]> Signed-off-by: Valentin Duperray <[email protected]> Signed-off-by: Franck Jonas <[email protected]> Signed-off-by: Lucien Kong <[email protected]> Signed-off-by: Thomas Nguy <[email protected]> Signed-off-by: Huynh Khoi Nguyen Nguyen <[email protected]> Signed-off-by: Matthieu Moy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fe67687 commit 21e5cfd

File tree

4 files changed

+119
-14
lines changed

4 files changed

+119
-14
lines changed

Documentation/git-bisect.txt

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ The command takes various subcommands, and different options depending
1717
on the subcommand:
1818

1919
git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
20-
git bisect bad [<rev>]
21-
git bisect good [<rev>...]
20+
git bisect (bad|new) [<rev>]
21+
git bisect (good|old) [<rev>...]
2222
git bisect skip [(<rev>|<range>)...]
2323
git bisect reset [<commit>]
2424
git bisect visualize
@@ -36,6 +36,13 @@ whether the selected commit is "good" or "bad". It continues narrowing
3636
down the range until it finds the exact commit that introduced the
3737
change.
3838

39+
In fact, `git bisect` can be used to find the commit that changed
40+
*any* property of your project; e.g., the commit that fixed a bug, or
41+
the commit that caused a benchmark's performance to improve. To
42+
support this more general usage, the terms "old" and "new" can be used
43+
in place of "good" and "bad". See
44+
section "Alternate terms" below for more information.
45+
3946
Basic bisect commands: start, bad, good
4047
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4148

@@ -111,6 +118,45 @@ bad revision, while `git bisect reset HEAD` will leave you on the
111118
current bisection commit and avoid switching commits at all.
112119

113120

121+
Alternate terms
122+
~~~~~~~~~~~~~~~
123+
124+
Sometimes you are not looking for the commit that introduced a
125+
breakage, but rather for a commit that caused a change between some
126+
other "old" state and "new" state. For example, you might be looking
127+
for the commit that introduced a particular fix. Or you might be
128+
looking for the first commit in which the source-code filenames were
129+
finally all converted to your company's naming standard. Or whatever.
130+
131+
In such cases it can be very confusing to use the terms "good" and
132+
"bad" to refer to "the state before the change" and "the state after
133+
the change". So instead, you can use the terms "old" and "new",
134+
respectively, in place of "good" and "bad". (But note that you cannot
135+
mix "good" and "bad" with "old" and "new" in a single session.)
136+
137+
In this more general usage, you provide `git bisect` with a "new"
138+
commit has some property and an "old" commit that doesn't have that
139+
property. Each time `git bisect` checks out a commit, you test if that
140+
commit has the property. If it does, mark the commit as "new";
141+
otherwise, mark it as "old". When the bisection is done, `git bisect`
142+
will report which commit introduced the property.
143+
144+
To use "old" and "new" instead of "good" and bad, you must run `git
145+
bisect start` without commits as argument and then run the following
146+
commands to add the commits:
147+
148+
------------------------------------------------
149+
git bisect old [<rev>]
150+
------------------------------------------------
151+
152+
to indicate that a commit was before the sought change, or
153+
154+
------------------------------------------------
155+
git bisect new [<rev>...]
156+
------------------------------------------------
157+
158+
to indicate that it was after.
159+
114160
Bisect visualize
115161
~~~~~~~~~~~~~~~~
116162

@@ -387,6 +433,14 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit
387433
has at least one parent whose reachable graph is fully traversable in the sense
388434
required by 'git pack objects'.
389435

436+
* Look for a fix instead of a regression in the code
437+
+
438+
------------
439+
$ git bisect start
440+
$ git bisect new HEAD # current commit is marked as new
441+
$ git bisect old HEAD~10 # the tenth commit from now is marked as old
442+
------------
443+
390444
Getting help
391445
~~~~~~~~~~~~
392446

bisect.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,11 @@ static void handle_bad_merge_base(void)
746746
"This means the bug has been fixed "
747747
"between %s and [%s].\n",
748748
bad_hex, bad_hex, good_hex);
749+
} else if (!strcmp(term_bad, "new") && !strcmp(term_good, "old")) {
750+
fprintf(stderr, "The merge base %s is new.\n"
751+
"The property has changed "
752+
"between %s and [%s].\n",
753+
bad_hex, bad_hex, good_hex);
749754
} else {
750755
fprintf(stderr, "The merge base %s is %s.\n"
751756
"This means the first '%s' commit is "
@@ -778,11 +783,11 @@ static void handle_skipped_merge_base(const unsigned char *mb)
778783
}
779784

780785
/*
781-
* "check_merge_bases" checks that merge bases are not "bad".
786+
* "check_merge_bases" checks that merge bases are not "bad" (or "new").
782787
*
783-
* - If one is "bad", it means the user assumed something wrong
788+
* - If one is "bad" (or "new"), it means the user assumed something wrong
784789
* and we must exit with a non 0 error code.
785-
* - If one is "good", that's good, we have nothing to do.
790+
* - If one is "good" (or "old"), that's good, we have nothing to do.
786791
* - If one is "skipped", we can't know but we should warn.
787792
* - If we don't know, we should check it out and ask the user to test.
788793
*/

git-bisect.sh

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
#!/bin/sh
22

3-
USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
3+
USAGE='[help|start|bad|good|new|old|skip|next|reset|visualize|replay|log|run]'
44
LONG_USAGE='git bisect help
55
print this long help message.
66
git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
77
reset bisect state and start bisection.
8-
git bisect bad [<rev>]
9-
mark <rev> a known-bad revision.
10-
git bisect good [<rev>...]
11-
mark <rev>... known-good revisions.
8+
git bisect (bad|new) [<rev>]
9+
mark <rev> a known-bad revision/
10+
a revision after change in a given property.
11+
git bisect (good|old) [<rev>...]
12+
mark <rev>... known-good revisions/
13+
revisions before change in a given property.
1214
git bisect skip [(<rev>|<range>)...]
1315
mark <rev>... untestable revisions.
1416
git bisect next
@@ -294,7 +296,7 @@ bisect_next_check() {
294296
false
295297
;;
296298
t,,"$TERM_GOOD")
297-
# have bad but not good. we could bisect although
299+
# have bad (or new) but not good (or old). we could bisect although
298300
# this is less optimum.
299301
eval_gettextln "Warning: bisecting only with a \$TERM_BAD commit." >&2
300302
if test -t 0
@@ -587,14 +589,20 @@ check_and_set_terms () {
587589
write_terms bad good
588590
fi
589591
;;
592+
new|old)
593+
if ! test -s "$GIT_DIR/BISECT_TERMS"
594+
then
595+
write_terms new old
596+
fi
597+
;;
590598
esac ;;
591599
esac
592600
}
593601

594602
bisect_voc () {
595603
case "$1" in
596-
bad) echo "bad" ;;
597-
good) echo "good" ;;
604+
bad) echo "bad|new" ;;
605+
good) echo "good|old" ;;
598606
esac
599607
}
600608

@@ -610,7 +618,7 @@ case "$#" in
610618
git bisect -h ;;
611619
start)
612620
bisect_start "$@" ;;
613-
bad|good|"$TERM_BAD"|"$TERM_GOOD")
621+
bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
614622
bisect_state "$cmd" "$@" ;;
615623
skip)
616624
bisect_skip "$@" ;;

t/t6030-bisect-porcelain.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,4 +759,42 @@ test_expect_success '"git bisect bad HEAD" behaves as "git bisect bad"' '
759759
git bisect reset
760760
'
761761

762+
test_expect_success 'bisect starts with only one new' '
763+
git bisect reset &&
764+
git bisect start &&
765+
git bisect new $HASH4 &&
766+
git bisect next
767+
'
768+
769+
test_expect_success 'bisect does not start with only one old' '
770+
git bisect reset &&
771+
git bisect start &&
772+
git bisect old $HASH1 &&
773+
test_must_fail git bisect next
774+
'
775+
776+
test_expect_success 'bisect start with one new and old' '
777+
git bisect reset &&
778+
git bisect start &&
779+
git bisect old $HASH1 &&
780+
git bisect new $HASH4 &&
781+
git bisect new &&
782+
git bisect new >bisect_result &&
783+
grep "$HASH2 is the first new commit" bisect_result &&
784+
git bisect log >log_to_replay.txt &&
785+
git bisect reset
786+
'
787+
788+
test_expect_success 'bisect replay with old and new' '
789+
git bisect replay log_to_replay.txt >bisect_result &&
790+
grep "$HASH2 is the first new commit" bisect_result &&
791+
git bisect reset
792+
'
793+
794+
test_expect_success 'bisect cannot mix old/new and good/bad' '
795+
git bisect start &&
796+
git bisect bad $HASH4 &&
797+
test_must_fail git bisect old $HASH1
798+
'
799+
762800
test_done

0 commit comments

Comments
 (0)