Bisect: teach "bisect start" to optionally use one bad and many good revs.
One bad commit is fundamentally needed for bisect to run, and if we beforehand know more good commits, we can narrow the bisect space down without doing the whole tree checkout every time we give good commits. This patch implements: git bisect start [<bad> [<good>...]] [--] [<pathspec>...] as a short-hand for this command sequence: git bisect start git bisect bad $bad git bisect good $good1 $good2... On the other hand, there may be some confusion between revs (<bad> and <good>...) and <pathspec>... if -- is not used and if an invalid rev or a pathspec that looks like a rev is given. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
33580fbd30
commit
38a47fd6e3
105
git-bisect.sh
105
git-bisect.sh
@ -1,15 +1,24 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
USAGE='[start|bad|good|next|reset|visualize|replay|log|run]'
|
USAGE='[start|bad|good|next|reset|visualize|replay|log|run]'
|
||||||
LONG_USAGE='git bisect start [<pathspec>] reset bisect state and start bisection.
|
LONG_USAGE='git bisect start [<bad> [<good>...]] [--] [<pathspec>...]
|
||||||
git bisect bad [<rev>] mark <rev> a known-bad revision.
|
reset bisect state and start bisection.
|
||||||
git bisect good [<rev>...] mark <rev>... known-good revisions.
|
git bisect bad [<rev>]
|
||||||
git bisect next find next bisection to test and check it out.
|
mark <rev> a known-bad revision.
|
||||||
git bisect reset [<branch>] finish bisection search and go back to branch.
|
git bisect good [<rev>...]
|
||||||
git bisect visualize show bisect status in gitk.
|
mark <rev>... known-good revisions.
|
||||||
git bisect replay <logfile> replay bisection log.
|
git bisect next
|
||||||
git bisect log show bisect log.
|
find next bisection to test and check it out.
|
||||||
git bisect run <cmd>... use <cmd>... to automatically bisect.'
|
git bisect reset [<branch>]
|
||||||
|
finish bisection search and go back to branch.
|
||||||
|
git bisect visualize
|
||||||
|
show bisect status in gitk.
|
||||||
|
git bisect replay <logfile>
|
||||||
|
replay bisection log.
|
||||||
|
git bisect log
|
||||||
|
show bisect log.
|
||||||
|
git bisect run <cmd>...
|
||||||
|
use <cmd>... to automatically bisect.'
|
||||||
|
|
||||||
. git-sh-setup
|
. git-sh-setup
|
||||||
require_work_tree
|
require_work_tree
|
||||||
@ -70,14 +79,48 @@ bisect_start() {
|
|||||||
#
|
#
|
||||||
# Get rid of any old bisect state
|
# Get rid of any old bisect state
|
||||||
#
|
#
|
||||||
rm -f "$GIT_DIR/refs/heads/bisect"
|
bisect_clean_state
|
||||||
rm -rf "$GIT_DIR/refs/bisect/"
|
|
||||||
mkdir "$GIT_DIR/refs/bisect"
|
mkdir "$GIT_DIR/refs/bisect"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check for one bad and then some good revisions.
|
||||||
|
#
|
||||||
|
has_double_dash=0
|
||||||
|
for arg; do
|
||||||
|
case "$arg" in --) has_double_dash=1; break ;; esac
|
||||||
|
done
|
||||||
|
orig_args=$(sq "$@")
|
||||||
|
bad_seen=0
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
arg="$1"
|
||||||
|
case "$arg" in
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
rev=$(git-rev-parse --verify "$arg^{commit}" 2>/dev/null) || {
|
||||||
|
test $has_double_dash -eq 1 &&
|
||||||
|
die "'$arg' does not appear to be a valid revision"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if [ $bad_seen -eq 0 ]; then
|
||||||
|
bad_seen=1
|
||||||
|
bisect_write_bad "$rev"
|
||||||
|
else
|
||||||
|
bisect_write_good "$rev"
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
sq "$@" >"$GIT_DIR/BISECT_NAMES"
|
||||||
{
|
{
|
||||||
printf "git-bisect start"
|
printf "git-bisect start"
|
||||||
sq "$@"
|
echo "$orig_args"
|
||||||
} >"$GIT_DIR/BISECT_LOG"
|
} >>"$GIT_DIR/BISECT_LOG"
|
||||||
sq "$@" >"$GIT_DIR/BISECT_NAMES"
|
bisect_auto_next
|
||||||
}
|
}
|
||||||
|
|
||||||
bisect_bad() {
|
bisect_bad() {
|
||||||
@ -90,12 +133,17 @@ bisect_bad() {
|
|||||||
*)
|
*)
|
||||||
usage ;;
|
usage ;;
|
||||||
esac || exit
|
esac || exit
|
||||||
echo "$rev" >"$GIT_DIR/refs/bisect/bad"
|
bisect_write_bad "$rev"
|
||||||
echo "# bad: "$(git-show-branch $rev) >>"$GIT_DIR/BISECT_LOG"
|
|
||||||
echo "git-bisect bad $rev" >>"$GIT_DIR/BISECT_LOG"
|
echo "git-bisect bad $rev" >>"$GIT_DIR/BISECT_LOG"
|
||||||
bisect_auto_next
|
bisect_auto_next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bisect_write_bad() {
|
||||||
|
rev="$1"
|
||||||
|
echo "$rev" >"$GIT_DIR/refs/bisect/bad"
|
||||||
|
echo "# bad: "$(git-show-branch $rev) >>"$GIT_DIR/BISECT_LOG"
|
||||||
|
}
|
||||||
|
|
||||||
bisect_good() {
|
bisect_good() {
|
||||||
bisect_autostart
|
bisect_autostart
|
||||||
case "$#" in
|
case "$#" in
|
||||||
@ -106,13 +154,19 @@ bisect_good() {
|
|||||||
for rev in $revs
|
for rev in $revs
|
||||||
do
|
do
|
||||||
rev=$(git-rev-parse --verify "$rev^{commit}") || exit
|
rev=$(git-rev-parse --verify "$rev^{commit}") || exit
|
||||||
echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev"
|
bisect_write_good "$rev"
|
||||||
echo "# good: "$(git-show-branch $rev) >>"$GIT_DIR/BISECT_LOG"
|
|
||||||
echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG"
|
echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG"
|
||||||
|
|
||||||
done
|
done
|
||||||
bisect_auto_next
|
bisect_auto_next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bisect_write_good() {
|
||||||
|
rev="$1"
|
||||||
|
echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev"
|
||||||
|
echo "# good: "$(git-show-branch $rev) >>"$GIT_DIR/BISECT_LOG"
|
||||||
|
}
|
||||||
|
|
||||||
bisect_next_check() {
|
bisect_next_check() {
|
||||||
next_ok=no
|
next_ok=no
|
||||||
test -f "$GIT_DIR/refs/bisect/bad" &&
|
test -f "$GIT_DIR/refs/bisect/bad" &&
|
||||||
@ -190,14 +244,19 @@ bisect_reset() {
|
|||||||
usage ;;
|
usage ;;
|
||||||
esac
|
esac
|
||||||
if git checkout "$branch"; then
|
if git checkout "$branch"; then
|
||||||
rm -fr "$GIT_DIR/refs/bisect"
|
rm -f "$GIT_DIR/head-name"
|
||||||
rm -f "$GIT_DIR/refs/heads/bisect" "$GIT_DIR/head-name"
|
bisect_clean_state
|
||||||
rm -f "$GIT_DIR/BISECT_LOG"
|
|
||||||
rm -f "$GIT_DIR/BISECT_NAMES"
|
|
||||||
rm -f "$GIT_DIR/BISECT_RUN"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bisect_clean_state() {
|
||||||
|
rm -fr "$GIT_DIR/refs/bisect"
|
||||||
|
rm -f "$GIT_DIR/refs/heads/bisect"
|
||||||
|
rm -f "$GIT_DIR/BISECT_LOG"
|
||||||
|
rm -f "$GIT_DIR/BISECT_NAMES"
|
||||||
|
rm -f "$GIT_DIR/BISECT_RUN"
|
||||||
|
}
|
||||||
|
|
||||||
bisect_replay () {
|
bisect_replay () {
|
||||||
test -r "$1" || {
|
test -r "$1" || {
|
||||||
echo >&2 "cannot read $1 for replaying"
|
echo >&2 "cannot read $1 for replaying"
|
||||||
|
@ -40,8 +40,8 @@ test_expect_success \
|
|||||||
# We want to automatically find the commit that
|
# We want to automatically find the commit that
|
||||||
# introduced "Another" into hello.
|
# introduced "Another" into hello.
|
||||||
test_expect_success \
|
test_expect_success \
|
||||||
'git bisect run simple case' \
|
'"git bisect run" simple case' \
|
||||||
'echo "#!/bin/sh" > test_script.sh &&
|
'echo "#"\!"/bin/sh" > test_script.sh &&
|
||||||
echo "grep Another hello > /dev/null" >> test_script.sh &&
|
echo "grep Another hello > /dev/null" >> test_script.sh &&
|
||||||
echo "test \$? -ne 0" >> test_script.sh &&
|
echo "test \$? -ne 0" >> test_script.sh &&
|
||||||
chmod +x test_script.sh &&
|
chmod +x test_script.sh &&
|
||||||
@ -49,7 +49,21 @@ test_expect_success \
|
|||||||
git bisect good $HASH1 &&
|
git bisect good $HASH1 &&
|
||||||
git bisect bad $HASH4 &&
|
git bisect bad $HASH4 &&
|
||||||
git bisect run ./test_script.sh > my_bisect_log.txt &&
|
git bisect run ./test_script.sh > my_bisect_log.txt &&
|
||||||
grep "$HASH3 is first bad commit" my_bisect_log.txt'
|
grep "$HASH3 is first bad commit" my_bisect_log.txt &&
|
||||||
|
git bisect reset'
|
||||||
|
|
||||||
|
# We want to automatically find the commit that
|
||||||
|
# introduced "Ciao" into hello.
|
||||||
|
test_expect_success \
|
||||||
|
'"git bisect run" with more complex "git bisect start"' \
|
||||||
|
'echo "#"\!"/bin/sh" > test_script.sh &&
|
||||||
|
echo "grep Ciao hello > /dev/null" >> test_script.sh &&
|
||||||
|
echo "test \$? -ne 0" >> test_script.sh &&
|
||||||
|
chmod +x test_script.sh &&
|
||||||
|
git bisect start $HASH4 $HASH1 &&
|
||||||
|
git bisect run ./test_script.sh > my_bisect_log.txt &&
|
||||||
|
grep "$HASH4 is first bad commit" my_bisect_log.txt &&
|
||||||
|
git bisect reset'
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user