[PATCH v3] bisect: teach "skip" to accept a range using "-r|--range" option
From: Christian Couder <hidden>
Date: 2016-06-15 22:45:42
Subsystem:
documentation, the rest · Maintainers:
Jonathan Corbet, Linus Torvalds
The current "git bisect skip" syntax is "git bisect skip [<rev>...]",
so it's already possible to skip a range of revisions using
something like:
$ git bisect skip $(git rev-list A..B)
where A and B are the bounds of the range of commits we want to skip.
In this case A itself will not be skipped, but B will be, because
that's how "git rev-list" works.
This patch teaches "git bisect skip" to accept:
$ git bisect skip --range=A,B
or:
$ git bisect skip -r A,B
to skip the whole range of commits between A included and B included.
Because we believe that users, in most cases, will want the first
bound to be skipped too.
If either A or B is ommited, HEAD will be used instead.
This is done by expanding each range argument using:
git rev-list "${B:-HEAD}" --not $(git rev-parse "${A:-HEAD}^@")
So the following command:
$ git bisect skip A -r B,C D E --range=F, --range ,G
should work as expected.
Signed-off-by: Christian Couder <redacted>
---
Documentation/git-bisect.txt | 30 +++++++++++++++++++++++-
git-bisect.sh | 52 ++++++++++++++++++++++++++++++++++++++++-
t/t6030-bisect-porcelain.sh | 10 +++++++-
3 files changed, 88 insertions(+), 4 deletions(-)
Junio wrote:
>
> Although I fully realize that the established semantics of A..B in git is
> bottom-exclusive, top-inclusive, and this suggestion breaks the UI
> uniformity by deviating from that convention, I have to wonder if it would
> be more useful if you let the bottom commit (A in your example) also be
> skipped.
I agree that it would be perhaps more usefull to skip the bottom commit.
But in this case I think we should not use the .. notation as it would be
inconsistent. So here is a patch that adds an all inclusive "-r|--range"
option.
This patch adds some documentation and a test case too.
After coming up with this patch, I saw that the previous version has
already been merged into "next" and "master", but perhaps it can be reverted
and this version applied. Otherwise if the previous version is preferred, I
will come up with another patch to just add some documentation and tests on
top of the previous version.
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 39034ec..86f6ad2 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt@@ -19,7 +19,7 @@ on the subcommand: git bisect start [<bad> [<good>...]] [--] [<paths>...] git bisect bad [<rev>] git bisect good [<rev>...] - git bisect skip [<rev>...] + git bisect skip [(<rev>|<range>)...] git bisect reset [<branch>] git bisect visualize git bisect replay <logfile>
@@ -164,6 +164,34 @@ But computing the commit to test may be slower afterwards and git may eventually not be able to tell the first bad among a bad and one or more "skip"ped commits. +You can even skip a range of commits, instead of just one commit, +using option -r|--range. For example: + +------------ +$ git bisect skip --range=v2.5,v2.6 +------------ + +or: + +------------ +$ git bisect skip -r v2.5,v2.6 +------------ + +would mean that no commit between versions 2.5 included and 2.6 +included can be tested. + +Note that you must take care that the first commit in the given range +is an ancestor of the second commit. + +Also note that if you don't want to skip the first commit of a range +you can use something like: + +------------ +$ git bisect skip $(git rev-list v2.5..v2.6) +------------ + +and the commit pointed to by v2.5 will not be skipped. + Cutting down bisection by giving more parameters to bisect start ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/git-bisect.sh b/git-bisect.sh
index 0d0e278..29a5c2e 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh@@ -9,7 +9,7 @@ git bisect bad [<rev>] mark <rev> a known-bad revision. git bisect good [<rev>...] mark <rev>... known-good revisions. -git bisect skip [<rev>...] +git bisect skip [(<rev>|<range>)...] mark <rev>... untestable revisions. git bisect next find next bisection to test and check it out.
@@ -191,6 +191,52 @@ check_expected_revs() { done } +list_range() { + case "$1" in + *,*) ;; # Ok + *) die "Bad range: $1" ;; + esac + + _A=$(expr "z$1" : 'z\([^,]*\),.*') + _B=$(expr "z$1" : 'z[^,]*,\(.*\)') + + # + # We want a range with both bounds included. + # ("git rev-list ^A B" would exclude commit A.) + # This means we want to exclude starting from the parents of _A, + # not starting from _A itself. + # + git rev-list "${_B:-HEAD}" --not $(git rev-parse "${_A:-HEAD}^@") +} + +bisect_skip() { + all='' + while test $# != 0 + do + case "$1" in + -r|--range*) + case "$#,$1" in + *,*=*) + range=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;; + 1,*) + die "Bad or incomplete range: $1" ;; + *) + range="$2"; shift ;; + esac + revs=$(list_range "$range") || + die "Bad rev input: $1" + ;; + *) + revs="'$arg'" + ;; + esac + shift + all="$all $revs" + done + bisect_state 'skip' $all +} + + bisect_state() { bisect_autostart state=$1
@@ -630,8 +676,10 @@ case "$#" in git bisect -h ;; start) bisect_start "$@" ;; - bad|good|skip) + bad|good) bisect_state "$cmd" "$@" ;; + skip) + bisect_skip "$@" ;; next) # Not sure we want "next" at the UI level anymore. bisect_next "$@" ;;
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 85fa39c..e76546c 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh@@ -313,8 +313,16 @@ test_expect_success 'bisect run & skip: find first bad' ' grep "$HASH6 is first bad commit" my_bisect_log.txt ' -test_expect_success 'bisect starting with a detached HEAD' ' +test_expect_success 'bisect skip range' ' + git bisect reset && + git bisect start $HASH7 $HASH1 && + git bisect skip --range=$HASH2,$HASH5 && + test "$HASH6" = "$(git rev-parse --verify HEAD)" && + test_must_fail git bisect bad > my_bisect_log.txt && + grep "first bad commit could be any of" my_bisect_log.txt +' +test_expect_success 'bisect starting with a detached HEAD' ' git bisect reset && git checkout master^ && HEAD=$(git rev-parse --verify HEAD) &&
--
1.6.0.4.772.ge8f9a