]> git.ipfire.org Git - thirdparty/git.git/blame - git-bisect.sh
bisect: add documentation for --no-checkout option.
[thirdparty/git.git] / git-bisect.sh
CommitLineData
8cc6a083 1#!/bin/sh
d025524d 2
243a60fb
CC
3USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
4LONG_USAGE='git bisect help
5 print this long help message.
4796e823 6git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
38a47fd6
CC
7 reset bisect state and start bisection.
8git bisect bad [<rev>]
9 mark <rev> a known-bad revision.
10git bisect good [<rev>...]
11 mark <rev>... known-good revisions.
5413812f 12git bisect skip [(<rev>|<range>)...]
6ca8b977 13 mark <rev>... untestable revisions.
38a47fd6
CC
14git bisect next
15 find next bisection to test and check it out.
6b87ce23
AK
16git bisect reset [<commit>]
17 finish bisection search and go back to commit.
38a47fd6
CC
18git bisect visualize
19 show bisect status in gitk.
20git bisect replay <logfile>
21 replay bisection log.
22git bisect log
23 show bisect log.
24git bisect run <cmd>...
243a60fb
CC
25 use <cmd>... to automatically bisect.
26
27Please use "git help bisect" to get the full man page.'
d025524d 28
8f321a39 29OPTIONS_SPEC=
ae2b0f15 30. git-sh-setup
dcf9c2e5 31. git-sh-i18n
4c550686 32require_work_tree
8cc6a083 33
ce32660e
JS
34_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
35_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
36
4796e823
JS
37bisect_head()
38{
39 if test -f "$GIT_DIR/BISECT_HEAD"
40 then
41 echo BISECT_HEAD
42 else
43 echo HEAD
44 fi
45}
46
8cc6a083 47bisect_autostart() {
823ea121 48 test -s "$GIT_DIR/BISECT_START" || {
ddd7a7c2
ÆAB
49 (
50 gettext "You need to start by \"git bisect start\"" &&
51 echo
52 ) >&2
8cc6a083
LT
53 if test -t 0
54 then
04de0996
ÆAB
55 # TRANSLATORS: Make sure to include [Y] and [n] in your
56 # translation. The program will only accept English input
57 # at this point.
58 gettext "Do you want me to do it for you [Y/n]? " >&2
8cc6a083
LT
59 read yesno
60 case "$yesno" in
61 [Nn]*)
62 exit ;;
63 esac
64 bisect_start
65 else
66 exit 1
67 fi
68 }
69}
70
71bisect_start() {
4764f464
JS
72 #
73 # Check for one bad and then some good revisions.
74 #
75 has_double_dash=0
76 for arg; do
77 case "$arg" in --) has_double_dash=1; break ;; esac
78 done
79 orig_args=$(git rev-parse --sq-quote "$@")
80 bad_seen=0
81 eval=''
4796e823 82 mode=''
4764f464
JS
83 while [ $# -gt 0 ]; do
84 arg="$1"
85 case "$arg" in
86 --)
87 shift
88 break
89 ;;
4796e823
JS
90 --no-checkout)
91 mode=--no-checkout
92 shift ;;
93 --*)
94 die "$(eval_gettext "unrecognised option: '\$arg'")" ;;
4764f464
JS
95 *)
96 rev=$(git rev-parse -q --verify "$arg^{commit}") || {
97 test $has_double_dash -eq 1 &&
98 die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
99 break
100 }
101 case $bad_seen in
102 0) state='bad' ; bad_seen=1 ;;
103 *) state='good' ;;
104 esac
6ba7acff 105 eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
4764f464
JS
106 shift
107 ;;
108 esac
109 done
110
8cc6a083 111 #
634f2464 112 # Verify HEAD.
8cc6a083 113 #
48949a18 114 head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) ||
ce32660e 115 head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) ||
9570fc1e 116 die "$(gettext "Bad HEAD - I need a HEAD")"
634f2464 117
ee831f7d 118 #
634f2464 119 # Check if we are bisecting.
ee831f7d 120 #
d3e54c88 121 start_head=''
634f2464
CC
122 if test -s "$GIT_DIR/BISECT_START"
123 then
124 # Reset to the rev from where we started.
9d0cd91c 125 start_head=$(cat "$GIT_DIR/BISECT_START")
4796e823
JS
126 if test "z$mode" != "z--no-checkout"
127 then
128 git checkout "$start_head" --
129 fi
634f2464
CC
130 else
131 # Get rev from where we start.
132 case "$head" in
133 refs/heads/*|$_x40)
134 # This error message should only be triggered by
135 # cogito usage, and cogito users should understand
136 # it relates to cg-seek.
137 [ -s "$GIT_DIR/head-name" ] &&
9570fc1e 138 die "$(gettext "won't bisect on seeked tree")"
634f2464
CC
139 start_head="${head#refs/heads/}"
140 ;;
141 *)
9570fc1e 142 die "$(gettext "Bad HEAD - strange symbolic ref")"
634f2464
CC
143 ;;
144 esac
145 fi
8cc6a083
LT
146
147 #
634f2464 148 # Get rid of any old bisect state.
8cc6a083 149 #
823ea121 150 bisect_clean_state || exit
38a47fd6 151
ba963de8
CC
152 #
153 # Change state.
154 # In case of mistaken revs or checkout error, or signals received,
155 # "bisect_auto_next" below may exit or misbehave.
156 # We have to trap this to be able to clean up using
157 # "bisect_clean_state".
158 #
159 trap 'bisect_clean_state' 0
160 trap 'exit 255' 1 2 3 15
161
162 #
163 # Write new start state.
164 #
4796e823
JS
165 echo "$start_head" >"$GIT_DIR/BISECT_START" && {
166 test "z$mode" != "z--no-checkout" ||
167 git update-ref --no-deref BISECT_HEAD "$start_head"
168 } &&
de52f5a8 169 git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
6ba7acff 170 eval "$eval true" &&
6c98c054 171 echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
ba963de8
CC
172 #
173 # Check if we can proceed to the next bisect state.
174 #
38a47fd6 175 bisect_auto_next
ba963de8
CC
176
177 trap '-' 0
8cc6a083
LT
178}
179
55624f9a
CC
180bisect_write() {
181 state="$1"
182 rev="$2"
737c74ee 183 nolog="$3"
55624f9a
CC
184 case "$state" in
185 bad) tag="$state" ;;
186 good|skip) tag="$state"-"$rev" ;;
15eaa049 187 *) die "$(eval_gettext "Bad bisect_write argument: \$state")" ;;
55624f9a 188 esac
ba963de8 189 git update-ref "refs/bisect/$tag" "$rev" || exit
f454cdc4 190 echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG"
6c98c054 191 test -n "$nolog" || echo "git bisect $state $rev" >>"$GIT_DIR/BISECT_LOG"
55624f9a
CC
192}
193
c9c4e2d5
CC
194is_expected_rev() {
195 test -f "$GIT_DIR/BISECT_EXPECTED_REV" &&
196 test "$1" = $(cat "$GIT_DIR/BISECT_EXPECTED_REV")
197}
198
c9c4e2d5
CC
199check_expected_revs() {
200 for _rev in "$@"; do
201 if ! is_expected_rev "$_rev"; then
202 rm -f "$GIT_DIR/BISECT_ANCESTORS_OK"
203 rm -f "$GIT_DIR/BISECT_EXPECTED_REV"
204 return
205 fi
206 done
207}
208
ee2314f5
CC
209bisect_skip() {
210 all=''
211 for arg in "$@"
212 do
213 case "$arg" in
214 *..*)
15eaa049 215 revs=$(git rev-list "$arg") || die "$(eval_gettext "Bad rev input: \$arg")" ;;
ee2314f5 216 *)
de52f5a8 217 revs=$(git rev-parse --sq-quote "$arg") ;;
ee2314f5
CC
218 esac
219 all="$all $revs"
220 done
1a66a489 221 eval bisect_state 'skip' $all
ee2314f5
CC
222}
223
155fc795 224bisect_state() {
8cc6a083 225 bisect_autostart
155fc795
CC
226 state=$1
227 case "$#,$state" in
228 0,*)
9570fc1e 229 die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
155fc795 230 1,bad|1,good|1,skip)
4796e823
JS
231 rev=$(git rev-parse --verify $(bisect_head)) ||
232 die "$(gettext "Bad rev input: $(bisect_head)")"
c9c4e2d5
CC
233 bisect_write "$state" "$rev"
234 check_expected_revs "$rev" ;;
e3389075 235 2,bad|*,good|*,skip)
155fc795 236 shift
d3e54c88 237 eval=''
e3389075 238 for rev in "$@"
155fc795 239 do
a179a303 240 sha=$(git rev-parse --verify "$rev^{commit}") ||
15eaa049 241 die "$(eval_gettext "Bad rev input: \$rev")"
d3e54c88
CC
242 eval="$eval bisect_write '$state' '$sha'; "
243 done
c9c4e2d5
CC
244 eval "$eval"
245 check_expected_revs "$@" ;;
e3389075 246 *,bad)
9570fc1e 247 die "$(gettext "'git bisect bad' can take only one argument.")" ;;
cc9f24d0
JH
248 *)
249 usage ;;
8cc6a083 250 esac
97e1c51e
CC
251 bisect_auto_next
252}
253
8cc6a083 254bisect_next_check() {
0a5280a9
JH
255 missing_good= missing_bad=
256 git show-ref -q --verify refs/bisect/bad || missing_bad=t
257 test -n "$(git for-each-ref "refs/bisect/good-*")" || missing_good=t
6fecf191 258
0a5280a9
JH
259 case "$missing_good,$missing_bad,$1" in
260 ,,*)
261 : have both good and bad - ok
262 ;;
263 *,)
264 # do not have both but not asked to fail - just report.
265 false
266 ;;
267 t,,good)
268 # have bad but not good. we could bisect although
269 # this is less optimum.
ddd7a7c2
ÆAB
270 (
271 gettext "Warning: bisecting only with a bad commit." &&
272 echo
273 ) >&2
0a5280a9
JH
274 if test -t 0
275 then
04de0996
ÆAB
276 # TRANSLATORS: Make sure to include [Y] and [n] in your
277 # translation. The program will only accept English input
278 # at this point.
279 gettext "Are you sure [Y/n]? " >&2
e5d3afd7
FM
280 read yesno
281 case "$yesno" in [Nn]*) exit 1 ;; esac
0a5280a9
JH
282 fi
283 : bisect without good...
284 ;;
8cc6a083 285 *)
be508d3a
ÆAB
286
287 if test -s "$GIT_DIR/BISECT_START"
288 then
289 (
290 gettext "You need to give me at least one good and one bad revisions.
291(You can use \"git bisect bad\" and \"git bisect good\" for that.)" &&
292 echo
293 ) >&2
294 else
295 (
296 gettext "You need to start by \"git bisect start\".
297You then need to give me at least one good and one bad revisions.
298(You can use \"git bisect bad\" and \"git bisect good\" for that.)" &&
299 echo
300 ) >&2
301 fi
0a5280a9 302 exit 1 ;;
8cc6a083
LT
303 esac
304}
305
306bisect_auto_next() {
434d036f 307 bisect_next_check && bisect_next || :
8cc6a083
LT
308}
309
310bisect_next() {
8fe26f44 311 case "$#" in 0) ;; *) usage ;; esac
8cc6a083 312 bisect_autostart
0a5280a9
JH
313 bisect_next_check good
314
0871984d 315 # Perform all bisection computation, display and checkout
4796e823 316 git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
5a1d31c7 317 res=$?
0a5280a9 318
5a1d31c7
CC
319 # Check if we should exit because bisection is finished
320 test $res -eq 10 && exit 0
0a5280a9 321
5a1d31c7
CC
322 # Check for an error in the bisection process
323 test $res -ne 0 && exit $res
324
325 return 0
8cc6a083
LT
326}
327
cc9f24d0
JH
328bisect_visualize() {
329 bisect_next_check fail
235997c9
JH
330
331 if test $# = 0
332 then
c4e4644e
JK
333 if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
334 type gitk >/dev/null 2>&1; then
335 set gitk
336 else
337 set git log
338 fi
235997c9
JH
339 else
340 case "$1" in
341 git*|tig) ;;
342 -*) set git log "$@" ;;
343 *) set git "$@" ;;
344 esac
345 fi
346
fc13aa3d 347 eval '"$@"' --bisect -- $(cat "$GIT_DIR/BISECT_NAMES")
cc9f24d0
JH
348}
349
8cc6a083 350bisect_reset() {
823ea121 351 test -s "$GIT_DIR/BISECT_START" || {
d0238a88 352 gettext "We are not bisecting."; echo
fce0499f
CC
353 return
354 }
8cc6a083 355 case "$#" in
823ea121 356 0) branch=$(cat "$GIT_DIR/BISECT_START") ;;
7d0c2d6f
ÆAB
357 1) git rev-parse --quiet --verify "$1^{commit}" > /dev/null || {
358 invalid="$1"
359 die "$(eval_gettext "'\$invalid' is not a valid commit")"
360 }
8cc6a083 361 branch="$1" ;;
8fe26f44 362 *)
8cc6a083
LT
363 usage ;;
364 esac
4796e823
JS
365 if ! test -f "$GIT_DIR/BISECT_HEAD"
366 then
367 if ! git checkout "$branch" --
368 then
369 die "$(eval_gettext "Could not check out original HEAD '\$branch'.
15eaa049 370Try 'git bisect reset <commit>'.")"
4796e823 371 fi
3bb8cf88 372 fi
4796e823 373 bisect_clean_state
e204de28
JH
374}
375
38a47fd6 376bisect_clean_state() {
947a604b 377 # There may be some refs packed during bisection.
634f2464 378 git for-each-ref --format='%(refname) %(objectname)' refs/bisect/\* |
947a604b
CC
379 while read ref hash
380 do
823ea121 381 git update-ref -d $ref $hash || exit
947a604b 382 done
c9c4e2d5
CC
383 rm -f "$GIT_DIR/BISECT_EXPECTED_REV" &&
384 rm -f "$GIT_DIR/BISECT_ANCESTORS_OK" &&
823ea121
CC
385 rm -f "$GIT_DIR/BISECT_LOG" &&
386 rm -f "$GIT_DIR/BISECT_NAMES" &&
387 rm -f "$GIT_DIR/BISECT_RUN" &&
9d0cd91c 388 # Cleanup head-name if it got left by an old version of git-bisect
823ea121 389 rm -f "$GIT_DIR/head-name" &&
4796e823
JS
390 git update-ref -d --no-deref BISECT_HEAD &&
391 # clean up BISECT_START last
823ea121 392 rm -f "$GIT_DIR/BISECT_START"
38a47fd6
CC
393}
394
e204de28 395bisect_replay () {
55a9fc80
ÆAB
396 file="$1"
397 test "$#" -eq 1 || die "$(gettext "No logfile given")"
398 test -r "$file" || die "$(eval_gettext "cannot read \$file for replaying")"
e204de28 399 bisect_reset
6c98c054 400 while read git bisect command rev
e204de28 401 do
6c98c054
MV
402 test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
403 if test "$git" = "git-bisect"; then
404 rev="$command"
405 command="$bisect"
406 fi
e204de28
JH
407 case "$command" in
408 start)
e9a45d75 409 cmd="bisect_start $rev"
737c74ee
CC
410 eval "$cmd" ;;
411 good|bad|skip)
412 bisect_write "$command" "$rev" ;;
e204de28 413 *)
9570fc1e 414 die "$(gettext "?? what are you talking about?")" ;;
e204de28 415 esac
55a9fc80 416 done <"$file"
e204de28 417 bisect_auto_next
8cc6a083
LT
418}
419
a17c4101 420bisect_run () {
83020120
CC
421 bisect_next_check fail
422
a17c4101
CC
423 while true
424 do
09209255
ÆAB
425 command="$@"
426 eval_gettext "running \$command"; echo
a17c4101
CC
427 "$@"
428 res=$?
429
430 # Check for really bad run error.
431 if [ $res -lt 0 -o $res -ge 128 ]; then
09209255
ÆAB
432 (
433 eval_gettext "bisect run failed:
434exit code \$res from '\$command' is < 0 or >= 128" &&
435 echo
436 ) >&2
a17c4101
CC
437 exit $res
438 fi
439
155fc795 440 # Find current state depending on run success or failure.
71b0251c
CC
441 # A special exit code of 125 means cannot test.
442 if [ $res -eq 125 ]; then
443 state='skip'
444 elif [ $res -gt 0 ]; then
155fc795 445 state='bad'
a17c4101 446 else
155fc795 447 state='good'
a17c4101
CC
448 fi
449
155fc795
CC
450 # We have to use a subshell because "bisect_state" can exit.
451 ( bisect_state $state > "$GIT_DIR/BISECT_RUN" )
a17c4101
CC
452 res=$?
453
454 cat "$GIT_DIR/BISECT_RUN"
455
e1622bfc 456 if sane_grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \
71b0251c 457 > /dev/null; then
ddd7a7c2
ÆAB
458 (
459 gettext "bisect run cannot continue any more" &&
460 echo
461 ) >&2
71b0251c
CC
462 exit $res
463 fi
464
a17c4101 465 if [ $res -ne 0 ]; then
c6649c92
ÆAB
466 (
467 eval_gettext "bisect run failed:
468'bisect_state \$state' exited with error code \$res" &&
469 echo
470 ) >&2
a17c4101
CC
471 exit $res
472 fi
473
e1622bfc 474 if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then
d0238a88 475 gettext "bisect run success"; echo
a17c4101
CC
476 exit 0;
477 fi
478
479 done
480}
481
412ff738 482bisect_log () {
9570fc1e 483 test -s "$GIT_DIR/BISECT_LOG" || die "$(gettext "We are not bisecting.")"
412ff738
SG
484 cat "$GIT_DIR/BISECT_LOG"
485}
a17c4101 486
8cc6a083
LT
487case "$#" in
4880)
489 usage ;;
490*)
491 cmd="$1"
492 shift
493 case "$cmd" in
243a60fb
CC
494 help)
495 git bisect -h ;;
8cc6a083
LT
496 start)
497 bisect_start "$@" ;;
ee2314f5 498 bad|good)
155fc795 499 bisect_state "$cmd" "$@" ;;
ee2314f5
CC
500 skip)
501 bisect_skip "$@" ;;
8cc6a083
LT
502 next)
503 # Not sure we want "next" at the UI level anymore.
504 bisect_next "$@" ;;
235997c9 505 visualize|view)
cc9f24d0 506 bisect_visualize "$@" ;;
8cc6a083
LT
507 reset)
508 bisect_reset "$@" ;;
e204de28
JH
509 replay)
510 bisect_replay "$@" ;;
511 log)
412ff738 512 bisect_log ;;
a17c4101
CC
513 run)
514 bisect_run "$@" ;;
8cc6a083
LT
515 *)
516 usage ;;
517 esac
518esac