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 <chriscool@xxxxxxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html