Raw
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Christian Couder
4 #
5 test_description='Tests git bisect functionality'
6
7 exec </dev/null
8
9 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
10 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
11
12 . ./test-lib.sh
13
14 add_line_into_file()
15 {
16 _line=$1
17 _file=$2
18
19 if [ -f "$_file" ]; then
20 echo "$_line" >> $_file || return $?
21 MSG="Add <$_line> into <$_file>."
22 else
23 echo "$_line" > $_file || return $?
24 git add $_file || return $?
25 MSG="Create file <$_file> with <$_line> inside."
26 fi
27
28 test_tick
29 git commit --quiet -m "$MSG" $_file
30 }
31
32 HASH1=
33 HASH2=
34 HASH3=
35 HASH4=
36
37 test_bisect_usage () {
38 local code="$1" &&
39 shift &&
40 cat >expect &&
41 test_expect_code $code "$@" >out 2>actual &&
42 test_must_be_empty out &&
43 test_cmp expect actual
44 }
45
46 test_bisect_state_file () {
47 local file &&
48 file=$(git rev-parse --git-path "$1") &&
49 test_path_is_file "$file"
50 }
51
52 test_bisect_state_missing () {
53 local file &&
54 file=$(git rev-parse --git-path "$1") &&
55 test_path_is_missing "$file"
56 }
57
58 bisect_start_and_finish () {
59 git bisect start "$1" $HASH4 $HASH2 &&
60 git bisect bad
61 }
62
63 bisect_run_reset_when_found () {
64 write_script test_script.sh <<-\EOF &&
65 ! grep Another hello >/dev/null
66 EOF
67 git bisect start $HASH4 $HASH2 &&
68 git bisect run "$1" ./test_script.sh >my_bisect_log.txt &&
69 test_grep "$HASH3 is the first .bad. commit" my_bisect_log.txt &&
70 test_bisect_state_missing BISECT_RUN
71 }
72
73 test_reset_when_found_fails () {
74 local pattern="$1" &&
75 local state_file="$2" &&
76 shift 2 &&
77 test_must_fail "$@" 2>err &&
78 test_grep -- "$pattern" err &&
79 test_bisect_state_missing "$state_file"
80 }
81
82 test_expect_success 'bisect usage' "
83 test_bisect_usage 1 git bisect reset extra1 extra2 <<-\EOF &&
84 error: 'git bisect reset' requires either no argument or a commit
85 EOF
86 test_bisect_usage 1 git bisect terms extra1 extra2 <<-\EOF &&
87 error: 'git bisect terms' requires 0 or 1 argument
88 EOF
89 test_bisect_usage 1 git bisect next extra1 <<-\EOF &&
90 error: 'git bisect next' requires 0 arguments
91 EOF
92 test_bisect_usage 1 git bisect log extra1 <<-\EOF &&
93 error: We are not bisecting.
94 EOF
95 test_bisect_usage 1 git bisect replay <<-\EOF &&
96 error: no logfile given
97 EOF
98 test_bisect_usage 1 git bisect run <<-\EOF
99 error: 'git bisect run' failed: no command provided.
100 EOF
101 "
102
103 test_expect_success 'set up basic repo with 1 file (hello) and 4 commits' '
104 add_line_into_file "1: Hello World" hello &&
105 HASH1=$(git rev-parse --verify HEAD) &&
106 add_line_into_file "2: A new day for git" hello &&
107 HASH2=$(git rev-parse --verify HEAD) &&
108 add_line_into_file "3: Another new day for git" hello &&
109 HASH3=$(git rev-parse --verify HEAD) &&
110 add_line_into_file "4: Ciao for now" hello &&
111 HASH4=$(git rev-parse --verify HEAD)
112 '
113
114 test_expect_success 'bisect starts with only one bad' '
115 git bisect reset &&
116 git bisect start &&
117 git bisect bad $HASH4 &&
118 git bisect next
119 '
120
121 test_expect_success 'bisect does not start with only one good' '
122 git bisect reset &&
123 git bisect start &&
124 git bisect good $HASH1 &&
125 test_must_fail git bisect next
126 '
127
128 test_expect_success 'bisect start with one bad and good' '
129 git bisect reset &&
130 git bisect start &&
131 git bisect good $HASH1 &&
132 git bisect bad $HASH4 &&
133 git bisect next
134 '
135
136 test_expect_success 'bisect fails if given any junk instead of revs' '
137 git bisect reset &&
138 test_must_fail git bisect start foo $HASH1 -- &&
139 test_must_fail git bisect start $HASH4 $HASH1 bar -- &&
140 test -z "$(git for-each-ref "refs/bisect/*")" &&
141 test -z "$(ls .git/BISECT_* 2>/dev/null)" &&
142 git bisect start &&
143 test_must_fail git bisect good foo $HASH1 &&
144 test_must_fail git bisect good $HASH1 bar &&
145 test_must_fail git bisect bad frotz &&
146 test_must_fail git bisect bad $HASH3 $HASH4 &&
147 test_must_fail git bisect skip bar $HASH3 &&
148 test_must_fail git bisect skip $HASH1 foo &&
149 test -z "$(git for-each-ref "refs/bisect/*")" &&
150 git bisect good $HASH1 &&
151 git bisect bad $HASH4
152 '
153
154 test_expect_success 'bisect start without -- takes unknown arg as pathspec' '
155 git bisect reset &&
156 git bisect start foo bar &&
157 test_grep foo ".git/BISECT_NAMES" &&
158 test_grep bar ".git/BISECT_NAMES"
159 '
160
161 test_expect_success 'bisect reset: back in a branch checked out also elsewhere' '
162 echo "shared" > branch.expect &&
163 test_bisect_reset() {
164 git -C $1 bisect start &&
165 git -C $1 bisect good $HASH1 &&
166 git -C $1 bisect bad $HASH3 &&
167 git -C $1 bisect reset &&
168 git -C $1 branch --show-current > branch.output &&
169 cmp branch.expect branch.output
170 } &&
171 test_when_finished "
172 git worktree remove wt1 &&
173 git worktree remove wt2 &&
174 git branch -d shared
175 " &&
176 git worktree add wt1 -b shared &&
177 git worktree add wt2 -f shared &&
178 # we test in both worktrees to ensure that works
179 # as expected with "first" and "next" worktrees
180 test_bisect_reset wt1 &&
181 test_bisect_reset wt2
182 '
183
184 test_expect_success 'bisect reset: back in the main branch' '
185 git bisect reset &&
186 echo "* main" > branch.expect &&
187 git branch > branch.output &&
188 cmp branch.expect branch.output
189 '
190
191 test_expect_success 'bisect reset: back in another branch' '
192 git checkout -b other &&
193 git bisect start &&
194 git bisect good $HASH1 &&
195 git bisect bad $HASH3 &&
196 git bisect reset &&
197 echo " main" > branch.expect &&
198 echo "* other" >> branch.expect &&
199 git branch > branch.output &&
200 cmp branch.expect branch.output
201 '
202
203 test_expect_success 'bisect reset when not bisecting' '
204 git bisect reset &&
205 git branch > branch.output &&
206 cmp branch.expect branch.output
207 '
208
209 test_expect_success 'bisect reset cleans up even when not bisecting' '
210 echo garbage >.git/BISECT_LOG &&
211 git bisect reset &&
212 test_path_is_missing .git/BISECT_LOG
213 '
214
215 test_expect_success 'bisect reset removes packed refs' '
216 git bisect reset &&
217 git bisect start &&
218 git bisect good $HASH1 &&
219 git bisect bad $HASH3 &&
220 git pack-refs --all --prune &&
221 git bisect next &&
222 git bisect reset &&
223 test -z "$(git for-each-ref "refs/bisect/*")" &&
224 test -z "$(git for-each-ref "refs/heads/bisect")"
225 '
226
227 test_expect_success 'bisect reset removes bisect state after --no-checkout' '
228 git bisect reset &&
229 git bisect start --no-checkout &&
230 git bisect good $HASH1 &&
231 git bisect bad $HASH3 &&
232 git bisect next &&
233 git bisect reset &&
234 test -z "$(git for-each-ref "refs/bisect/*")" &&
235 test -z "$(git for-each-ref "refs/heads/bisect")" &&
236 test -z "$(git for-each-ref "BISECT_HEAD")"
237 '
238
239 test_expect_success 'bisect start: back in good branch' '
240 git branch > branch.output &&
241 grep "* other" branch.output > /dev/null &&
242 git bisect start $HASH4 $HASH1 -- &&
243 git bisect good &&
244 git bisect start $HASH4 $HASH1 -- &&
245 git bisect bad &&
246 git bisect reset &&
247 git branch > branch.output &&
248 grep "* other" branch.output > /dev/null
249 '
250
251 test_expect_success 'bisect start: no ".git/BISECT_START" created if junk rev' '
252 git bisect reset &&
253 test_must_fail git bisect start $HASH4 foo -- &&
254 git branch > branch.output &&
255 grep "* other" branch.output > /dev/null &&
256 test_path_is_missing .git/BISECT_START
257 '
258
259 test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if junk rev' '
260 git bisect start $HASH4 $HASH1 -- &&
261 git bisect good &&
262 cp .git/BISECT_START saved &&
263 test_must_fail git bisect start $HASH4 foo -- &&
264 git branch > branch.output &&
265 test_grep "* (no branch, bisect started on other)" branch.output > /dev/null &&
266 test_cmp saved .git/BISECT_START
267 '
268 test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
269 git bisect start $HASH4 $HASH1 -- &&
270 git bisect good &&
271 test_must_fail git bisect start $HASH1 $HASH4 -- &&
272 git branch > branch.output &&
273 grep "* other" branch.output > /dev/null &&
274 test_path_is_missing .git/BISECT_START
275 '
276
277 test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' '
278 echo "temp stuff" > hello &&
279 test_must_fail git bisect start $HASH4 $HASH1 -- &&
280 git branch &&
281 git branch > branch.output &&
282 grep "* other" branch.output > /dev/null &&
283 test_path_is_missing .git/BISECT_START &&
284 test -z "$(git for-each-ref "refs/bisect/*")" &&
285 git checkout HEAD hello
286 '
287
288 # $HASH1 is good, $HASH4 is bad, we skip $HASH3
289 # but $HASH2 is bad,
290 # so we should find $HASH2 as the first bad commit
291 test_expect_success 'bisect skip: successful result' '
292 test_when_finished git bisect reset &&
293 git bisect reset &&
294 git bisect start $HASH4 $HASH1 &&
295 git bisect skip &&
296 git bisect bad > my_bisect_log.txt &&
297 test_grep "$HASH2 is the first '\''bad'\'' commit" my_bisect_log.txt
298 '
299
300 # $HASH1 is good, $HASH4 is bad, we skip $HASH3 and $HASH2
301 # so we should not be able to tell the first bad commit
302 # among $HASH2, $HASH3 and $HASH4
303 test_expect_success 'bisect skip: cannot tell between 3 commits' '
304 test_when_finished git bisect reset &&
305 git bisect start $HASH4 $HASH1 &&
306 git bisect skip &&
307 test_expect_code 2 git bisect skip >my_bisect_log.txt &&
308 test_grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
309 test_grep ! $HASH1 my_bisect_log.txt &&
310 test_grep $HASH2 my_bisect_log.txt &&
311 test_grep $HASH3 my_bisect_log.txt &&
312 test_grep $HASH4 my_bisect_log.txt
313 '
314
315 # $HASH1 is good, $HASH4 is bad, we skip $HASH3
316 # but $HASH2 is good,
317 # so we should not be able to tell the first bad commit
318 # among $HASH3 and $HASH4
319 test_expect_success 'bisect skip: cannot tell between 2 commits' '
320 test_when_finished git bisect reset &&
321 git bisect start $HASH4 $HASH1 &&
322 git bisect skip &&
323 test_expect_code 2 git bisect good >my_bisect_log.txt &&
324 test_grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
325 test_grep ! $HASH1 my_bisect_log.txt &&
326 test_grep ! $HASH2 my_bisect_log.txt &&
327 test_grep $HASH3 my_bisect_log.txt &&
328 test_grep $HASH4 my_bisect_log.txt
329 '
330
331 # $HASH1 is good, $HASH4 is both skipped and bad, we skip $HASH3
332 # and $HASH2 is good,
333 # so we should not be able to tell the first bad commit
334 # among $HASH3 and $HASH4
335 test_expect_success 'bisect skip: with commit both bad and skipped' '
336 test_when_finished git bisect reset &&
337 git bisect start &&
338 git bisect skip &&
339 git bisect bad &&
340 git bisect good $HASH1 &&
341 git bisect skip &&
342 test_expect_code 2 git bisect good >my_bisect_log.txt &&
343 test_grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
344 test_grep ! $HASH1 my_bisect_log.txt &&
345 test_grep ! $HASH2 my_bisect_log.txt &&
346 test_grep $HASH3 my_bisect_log.txt &&
347 test_grep $HASH4 my_bisect_log.txt
348 '
349
350 test_bisect_run_args () {
351 test_when_finished "rm -f run.sh actual" &&
352 >actual &&
353 cat >expect.args &&
354 cat <&6 >expect.out &&
355 cat <&7 >expect.err &&
356 write_script run.sh <<-\EOF &&
357 while test $# != 0
358 do
359 echo "<$1>" &&
360 shift
361 done >actual.args
362 EOF
363
364 test_when_finished "git bisect reset" &&
365 git bisect start &&
366 git bisect good $HASH1 &&
367 git bisect bad $HASH4 &&
368 git bisect run ./run.sh $@ >actual.out.raw 2>actual.err &&
369 # Prune just the log output
370 sed -n \
371 -e '/^Author:/d' \
372 -e '/^Date:/d' \
373 -e '/^$/d' \
374 -e '/^commit /d' \
375 -e '/^ /d' \
376 -e 'p' \
377 <actual.out.raw >actual.out &&
378 test_cmp expect.out actual.out &&
379 test_cmp expect.err actual.err &&
380 test_cmp expect.args actual.args
381 }
382
383 test_expect_success 'git bisect run: args, stdout and stderr with no arguments' "
384 test_bisect_run_args <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
385 EOF_ARGS
386 running './run.sh'
387 $HASH4 is the first 'bad' commit
388 bisect found first 'bad' commit
389 EOF_OUT
390 EOF_ERR
391 "
392
393 test_expect_success 'git bisect run: args, stdout and stderr: "--" argument' "
394 test_bisect_run_args -- <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
395 <-->
396 EOF_ARGS
397 running './run.sh' '--'
398 $HASH4 is the first 'bad' commit
399 bisect found first 'bad' commit
400 EOF_OUT
401 EOF_ERR
402 "
403
404 test_expect_success 'git bisect run: args, stdout and stderr: "--log foo --no-log bar" arguments' "
405 test_bisect_run_args --log foo --no-log bar <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
406 <--log>
407 <foo>
408 <--no-log>
409 <bar>
410 EOF_ARGS
411 running './run.sh' '--log' 'foo' '--no-log' 'bar'
412 $HASH4 is the first 'bad' commit
413 bisect found first 'bad' commit
414 EOF_OUT
415 EOF_ERR
416 "
417
418 test_expect_success 'git bisect run: args, stdout and stderr: "--bisect-start" argument' "
419 test_bisect_run_args --bisect-start <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
420 <--bisect-start>
421 EOF_ARGS
422 running './run.sh' '--bisect-start'
423 $HASH4 is the first 'bad' commit
424 bisect found first 'bad' commit
425 EOF_OUT
426 EOF_ERR
427 "
428
429 test_expect_success 'git bisect run: negative exit code' "
430 write_script fail.sh <<-'EOF' &&
431 exit 255
432 EOF
433 cat <<-'EOF' >expect &&
434 bisect run failed: exit code -1 from './fail.sh' is < 0 or >= 128
435 EOF
436 test_when_finished 'git bisect reset' &&
437 git bisect start &&
438 git bisect good $HASH1 &&
439 git bisect bad $HASH4 &&
440 ! git bisect run ./fail.sh 2>err &&
441 sed -E -n 's/.*(bisect.*code) (-?[0-9]+) (from.*)/\1 -1 \3/p' err >actual &&
442 test_cmp expect actual
443 "
444
445 test_expect_success 'git bisect run: unable to verify on good' "
446 write_script fail.sh <<-'EOF' &&
447 head=\$(git rev-parse --verify HEAD)
448 good=\$(git rev-parse --verify $HASH1)
449 if test "\$head" = "\$good"
450 then
451 exit 255
452 else
453 exit 127
454 fi
455 EOF
456 cat <<-'EOF' >expect &&
457 unable to verify './fail.sh' on 'good' revision
458 EOF
459 test_when_finished 'git bisect reset' &&
460 git bisect start &&
461 git bisect good $HASH1 &&
462 git bisect bad $HASH4 &&
463 ! git bisect run ./fail.sh 2>err &&
464 sed -n 's/.*\(unable to verify.*\)/\1/p' err >actual &&
465 test_cmp expect actual
466 "
467
468 # We want to automatically find the commit that
469 # added "Another" into hello.
470 test_expect_success '"git bisect run" simple case' '
471 write_script test_script.sh <<-\EOF &&
472 ! grep Another hello >/dev/null
473 EOF
474 git bisect start &&
475 git bisect good $HASH1 &&
476 git bisect bad $HASH4 &&
477 git bisect run ./test_script.sh >my_bisect_log.txt &&
478 test_grep "$HASH3 is the first '\''bad'\'' commit" my_bisect_log.txt &&
479 git bisect reset
480 '
481
482 # We want to make sure no arguments has been eaten
483 test_expect_success '"git bisect run" simple case' '
484 git bisect start &&
485 git bisect good $HASH1 &&
486 git bisect bad $HASH4 &&
487 git bisect run printf "%s %s\n" reset --bisect-skip >my_bisect_log.txt &&
488 test_grep -e "reset --bisect-skip" my_bisect_log.txt &&
489 git bisect reset
490 '
491
492 test_expect_success '"git bisect start --reset-when-found" defaults to original' '
493 test_when_finished "git bisect reset && git checkout main" &&
494 git checkout main &&
495 bisect_start_and_finish --reset-when-found &&
496 actual=$(git rev-parse HEAD) &&
497 test "$HASH4" = "$actual" &&
498 actual=$(git branch --show-current) &&
499 test main = "$actual" &&
500 test_bisect_state_missing BISECT_START &&
501
502 bisect_start_and_finish --reset-when-found=original &&
503 actual=$(git rev-parse HEAD) &&
504 test "$HASH4" = "$actual" &&
505 actual=$(git branch --show-current) &&
506 test main = "$actual" &&
507 test_bisect_state_missing BISECT_START
508 '
509
510 test_expect_success '"git bisect start --reset-when-found=found" leaves first bad checked out' '
511 test_when_finished "git bisect reset && git checkout main" &&
512 bisect_start_and_finish --reset-when-found=found &&
513 actual=$(git rev-parse HEAD) &&
514 test "$HASH3" = "$actual" &&
515 test_bisect_state_missing BISECT_START
516 '
517
518 test_expect_success '"git bisect run --reset-when-found" defaults to original' '
519 test_when_finished "git bisect reset && git checkout main" &&
520 bisect_run_reset_when_found --reset-when-found &&
521 actual=$(git rev-parse HEAD) &&
522 test "$HASH4" = "$actual" &&
523 actual=$(git branch --show-current) &&
524 test main = "$actual" &&
525 test_bisect_state_missing BISECT_START
526 '
527
528 test_expect_success '"git bisect run --reset-when-found=found" leaves first bad checked out' '
529 test_when_finished "git bisect reset && git checkout main" &&
530 bisect_run_reset_when_found --reset-when-found=found &&
531 actual=$(git rev-parse HEAD) &&
532 test "$HASH3" = "$actual" &&
533 test_bisect_state_missing BISECT_START
534 '
535
536 test_expect_success '--reset-when-found rejects an unknown reset target' '
537 test_when_finished "git bisect reset && git checkout main" &&
538 test_reset_when_found_fails \
539 "invalid value for.*--reset-when-found.*unknown" BISECT_START \
540 git bisect start --reset-when-found=unknown $HASH4 $HASH2 &&
541
542 git bisect start $HASH4 $HASH2 &&
543 test_reset_when_found_fails \
544 "invalid value for.*--reset-when-found.*unknown" \
545 BISECT_RESET_WHEN_FOUND \
546 git bisect run --reset-when-found=unknown true
547 '
548
549 test_expect_success '--reset-when-found cannot be used with --no-checkout' '
550 test_when_finished "git bisect reset" &&
551 test_reset_when_found_fails \
552 "options .*--reset-when-found.* and .*--no-checkout.* cannot be used together" BISECT_START \
553 git bisect start --reset-when-found=original --no-checkout $HASH4 $HASH2 &&
554
555 git bisect start --no-checkout $HASH4 $HASH2 &&
556 test_reset_when_found_fails \
557 "options .*--reset-when-found.* and .*--no-checkout.* cannot be used together" BISECT_RESET_WHEN_FOUND \
558 git bisect run --reset-when-found=found true
559 '
560
561 test_expect_success 'without --reset-when-found the bisection state is kept' '
562 test_when_finished "git bisect reset" &&
563 git bisect start $HASH4 $HASH2 &&
564 git bisect bad &&
565 test_bisect_state_file BISECT_START
566 '
567
568 test_expect_success '--reset-when-found does not leak into a later bisection' '
569 test_when_finished "git bisect reset && git checkout main" &&
570 bisect_start_and_finish --reset-when-found &&
571
572 git bisect start $HASH4 $HASH2 &&
573 git bisect bad &&
574 test_bisect_state_file BISECT_START
575 '
576
577 # We want to automatically find the commit that
578 # added "Ciao" into hello.
579 test_expect_success '"git bisect run" with more complex "git bisect start"' '
580 write_script test_script.sh <<-\EOF &&
581 ! grep Ciao hello >/dev/null
582 EOF
583 git bisect start $HASH4 $HASH1 &&
584 git bisect run ./test_script.sh >my_bisect_log.txt &&
585 test_grep "$HASH4 is the first '\''bad'\'' commit" my_bisect_log.txt &&
586 git bisect reset
587 '
588
589 test_expect_success 'bisect run accepts exit code 126 as bad' '
590 test_when_finished "git bisect reset" &&
591 write_script test_script.sh <<-\EOF &&
592 ! grep Another hello || exit 126 >/dev/null
593 EOF
594 git bisect start &&
595 git bisect good $HASH1 &&
596 git bisect bad $HASH4 &&
597 git bisect run ./test_script.sh >my_bisect_log.txt &&
598 test_grep "$HASH3 is the first '\''bad'\'' commit" my_bisect_log.txt
599 '
600
601 test_expect_success POSIXPERM 'bisect run fails with non-executable test script' '
602 test_when_finished "git bisect reset" &&
603 >not-executable.sh &&
604 chmod -x not-executable.sh &&
605 git bisect start &&
606 git bisect good $HASH1 &&
607 git bisect bad $HASH4 &&
608 test_must_fail git bisect run ./not-executable.sh >my_bisect_log.txt &&
609 test_grep ! "is the first '\''bad'\'' commit" my_bisect_log.txt
610 '
611
612 test_expect_success 'bisect run accepts exit code 127 as bad' '
613 test_when_finished "git bisect reset" &&
614 write_script test_script.sh <<-\EOF &&
615 ! grep Another hello || exit 127 >/dev/null
616 EOF
617 git bisect start &&
618 git bisect good $HASH1 &&
619 git bisect bad $HASH4 &&
620 git bisect run ./test_script.sh >my_bisect_log.txt &&
621 test_grep "$HASH3 is the first '\''bad'\'' commit" my_bisect_log.txt
622 '
623
624 test_expect_success 'bisect run fails with missing test script' '
625 test_when_finished "git bisect reset" &&
626 rm -f does-not-exist.sh &&
627 git bisect start &&
628 git bisect good $HASH1 &&
629 git bisect bad $HASH4 &&
630 test_must_fail git bisect run ./does-not-exist.sh >my_bisect_log.txt &&
631 test_grep ! "is the first '\''bad'\'' commit" my_bisect_log.txt
632 '
633
634 # $HASH1 is good, $HASH5 is bad, we skip $HASH3
635 # but $HASH4 is good,
636 # so we should find $HASH5 as the first bad commit
637 HASH5=
638 test_expect_success 'bisect skip: add line and then a new test' '
639 add_line_into_file "5: Another new line." hello &&
640 HASH5=$(git rev-parse --verify HEAD) &&
641 git bisect start $HASH5 $HASH1 &&
642 git bisect skip &&
643 git bisect good > my_bisect_log.txt &&
644 test_grep "$HASH5 is the first '\''bad'\'' commit" my_bisect_log.txt &&
645 git bisect log > log_to_replay.txt &&
646 git bisect reset
647 '
648
649 test_expect_success 'bisect skip and bisect replay' '
650 git bisect replay log_to_replay.txt > my_bisect_log.txt &&
651 test_grep "$HASH5 is the first '\''bad'\'' commit" my_bisect_log.txt &&
652 git bisect reset
653 '
654
655 HASH6=
656 test_expect_success 'bisect run & skip: cannot tell between 2' '
657 add_line_into_file "6: Yet a line." hello &&
658 HASH6=$(git rev-parse --verify HEAD) &&
659 write_script test_script.sh <<-\EOF &&
660 sed -ne \$p hello | grep Ciao >/dev/null && exit 125
661 ! grep line hello >/dev/null
662 EOF
663 git bisect start $HASH6 $HASH1 &&
664 test_expect_code 2 git bisect run ./test_script.sh >my_bisect_log.txt &&
665 test_grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
666 test_grep ! $HASH3 my_bisect_log.txt &&
667 test_grep ! $HASH6 my_bisect_log.txt &&
668 test_grep $HASH4 my_bisect_log.txt &&
669 test_grep $HASH5 my_bisect_log.txt
670 '
671
672 HASH7=
673 test_expect_success 'bisect run & skip: find first bad' '
674 git bisect reset &&
675 add_line_into_file "7: Should be the last line." hello &&
676 HASH7=$(git rev-parse --verify HEAD) &&
677 write_script test_script.sh <<-\EOF &&
678 sed -ne \$p hello | grep Ciao >/dev/null && exit 125
679 sed -ne \$p hello | grep day >/dev/null && exit 125
680 ! grep Yet hello >/dev/null
681 EOF
682 git bisect start $HASH7 $HASH1 &&
683 git bisect run ./test_script.sh >my_bisect_log.txt &&
684 test_grep "$HASH6 is the first '\''bad'\'' commit" my_bisect_log.txt
685 '
686
687 test_expect_success 'bisect skip only one range' '
688 git bisect reset &&
689 git bisect start $HASH7 $HASH1 &&
690 git bisect skip $HASH1..$HASH5 &&
691 test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
692 test_must_fail git bisect bad > my_bisect_log.txt &&
693 test_grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt
694 '
695
696 test_expect_success 'bisect skip many ranges' '
697 git bisect start $HASH7 $HASH1 &&
698 test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
699 git bisect skip $HASH2 $HASH2.. ..$HASH5 &&
700 test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
701 test_must_fail git bisect bad > my_bisect_log.txt &&
702 test_grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt
703 '
704
705 test_expect_success 'bisect starting with a detached HEAD' '
706 git bisect reset &&
707 git checkout main^ &&
708 HEAD=$(git rev-parse --verify HEAD) &&
709 git bisect start &&
710 test $HEAD = $(cat .git/BISECT_START) &&
711 git bisect reset &&
712 test $HEAD = $(git rev-parse --verify HEAD)
713 '
714
715 test_expect_success 'bisect errors out if bad and good are mistaken' '
716 git bisect reset &&
717 test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
718 test_grep "mistook '\''good'\'' and '\''bad'\''" rev_list_error &&
719 git bisect reset
720 '
721
722 test_expect_success 'bisect does not create a "bisect" branch' '
723 git bisect reset &&
724 git bisect start $HASH7 $HASH1 &&
725 git branch bisect &&
726 rev_hash4=$(git rev-parse --verify HEAD) &&
727 test "$rev_hash4" = "$HASH4" &&
728 git branch -D bisect &&
729 git bisect good &&
730 git branch bisect &&
731 rev_hash6=$(git rev-parse --verify HEAD) &&
732 test "$rev_hash6" = "$HASH6" &&
733 git bisect good > my_bisect_log.txt &&
734 test_grep "$HASH7 is the first '\''bad'\'' commit" my_bisect_log.txt &&
735 git bisect reset &&
736 rev_hash6=$(git rev-parse --verify bisect) &&
737 test "$rev_hash6" = "$HASH6" &&
738 git branch -D bisect
739 '
740
741 # This creates a "side" branch to test "siblings" cases.
742 #
743 # H1-H2-H3-H4-H5-H6-H7 <--other
744 # \
745 # S5-S6-S7 <--side
746 #
747 test_expect_success 'side branch creation' '
748 git bisect reset &&
749 git checkout -b side $HASH4 &&
750 add_line_into_file "5(side): first line on a side branch" hello2 &&
751 SIDE_HASH5=$(git rev-parse --verify HEAD) &&
752 add_line_into_file "6(side): second line on a side branch" hello2 &&
753 SIDE_HASH6=$(git rev-parse --verify HEAD) &&
754 add_line_into_file "7(side): third line on a side branch" hello2 &&
755 SIDE_HASH7=$(git rev-parse --verify HEAD)
756 '
757
758 test_expect_success 'good merge base when good and bad are siblings' '
759 git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
760 test_grep "merge base must be tested" my_bisect_log.txt &&
761 test_grep $HASH4 my_bisect_log.txt &&
762 git bisect good > my_bisect_log.txt &&
763 test_grep ! "merge base must be tested" my_bisect_log.txt &&
764 test_grep $HASH6 my_bisect_log.txt &&
765 git bisect reset
766 '
767 test_expect_success 'skipped merge base when good and bad are siblings' '
768 git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt &&
769 test_grep "merge base must be tested" my_bisect_log.txt &&
770 test_grep $HASH4 my_bisect_log.txt &&
771 git bisect skip > my_bisect_log.txt 2>&1 &&
772 test_grep "warning" my_bisect_log.txt &&
773 test_grep $SIDE_HASH6 my_bisect_log.txt &&
774 git bisect reset
775 '
776
777 test_expect_success 'bad merge base when good and bad are siblings' '
778 git bisect start "$HASH7" HEAD > my_bisect_log.txt &&
779 test_grep "merge base must be tested" my_bisect_log.txt &&
780 test_grep $HASH4 my_bisect_log.txt &&
781 test_must_fail git bisect bad > my_bisect_log.txt 2>&1 &&
782 test_grep "merge base $HASH4 is bad" my_bisect_log.txt &&
783 test_grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt &&
784 git bisect reset
785 '
786
787 # This creates a few more commits (A and B) to test "siblings" cases
788 # when a good and a bad rev have many merge bases.
789 #
790 # We should have the following:
791 #
792 # H1-H2-H3-H4-H5-H6-H7
793 # \ \ \
794 # S5-A \
795 # \ \
796 # S6-S7----B
797 #
798 # And there A and B have 2 merge bases (S5 and H5) that should be
799 # reported by "git merge-base --all A B".
800 #
801 test_expect_success 'many merge bases creation' '
802 git checkout "$SIDE_HASH5" &&
803 git merge -m "merge HASH5 and SIDE_HASH5" "$HASH5" &&
804 A_HASH=$(git rev-parse --verify HEAD) &&
805 git checkout side &&
806 git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" &&
807 B_HASH=$(git rev-parse --verify HEAD) &&
808 git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt &&
809 test_line_count = 2 merge_bases.txt &&
810 test_grep "$HASH5" merge_bases.txt &&
811 test_grep "$SIDE_HASH5" merge_bases.txt
812 '
813
814 # We want to automatically find the merge that
815 # added "line" into hello.
816 test_expect_success '"git bisect run --first-parent" simple case' '
817 git rev-list --first-parent $B_HASH ^$HASH4 >first_parent_chain.txt &&
818 write_script test_script.sh <<-\EOF &&
819 grep $(git rev-parse HEAD) first_parent_chain.txt || exit -1
820 ! grep line hello >/dev/null
821 EOF
822 git bisect start --first-parent &&
823 test_path_is_file ".git/BISECT_FIRST_PARENT" &&
824 git bisect good $HASH4 &&
825 git bisect bad $B_HASH &&
826 git bisect run ./test_script.sh >my_bisect_log.txt &&
827 test_grep "$B_HASH is the first '\''bad'\'' commit" my_bisect_log.txt &&
828 git bisect reset &&
829 test_path_is_missing .git/BISECT_FIRST_PARENT
830 '
831
832 test_expect_success 'good merge bases when good and bad are siblings' '
833 git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt &&
834 test_grep "merge base must be tested" my_bisect_log.txt &&
835 git bisect good > my_bisect_log2.txt &&
836 test_grep "merge base must be tested" my_bisect_log2.txt &&
837 {
838 {
839 test_grep "$SIDE_HASH5" my_bisect_log.txt &&
840 test_grep "$HASH5" my_bisect_log2.txt
841 } || {
842 test_grep "$SIDE_HASH5" my_bisect_log2.txt &&
843 test_grep "$HASH5" my_bisect_log.txt
844 }
845 } &&
846 git bisect reset
847 '
848
849 test_expect_success 'optimized merge base checks' '
850 git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
851 test_grep "merge base must be tested" my_bisect_log.txt &&
852 test_grep "$HASH4" my_bisect_log.txt &&
853 git bisect good > my_bisect_log2.txt &&
854 test -f ".git/BISECT_ANCESTORS_OK" &&
855 test "$HASH6" = $(git rev-parse --verify HEAD) &&
856 git bisect bad &&
857 git bisect good "$A_HASH" > my_bisect_log4.txt &&
858 test_grep "merge base must be tested" my_bisect_log4.txt &&
859 test_path_is_missing ".git/BISECT_ANCESTORS_OK"
860 '
861
862 # This creates another side branch called "parallel" with some files
863 # in some directories, to test bisecting with paths.
864 #
865 # We should have the following:
866 #
867 # P1-P2-P3-P4-P5-P6-P7
868 # / / /
869 # H1-H2-H3-H4-H5-H6-H7
870 # \ \ \
871 # S5-A \
872 # \ \
873 # S6-S7----B
874 #
875 test_expect_success '"parallel" side branch creation' '
876 git bisect reset &&
877 git checkout -b parallel $HASH1 &&
878 mkdir dir1 dir2 &&
879 add_line_into_file "1(para): line 1 on parallel branch" dir1/file1 &&
880 PARA_HASH1=$(git rev-parse --verify HEAD) &&
881 add_line_into_file "2(para): line 2 on parallel branch" dir2/file2 &&
882 PARA_HASH2=$(git rev-parse --verify HEAD) &&
883 add_line_into_file "3(para): line 3 on parallel branch" dir2/file3 &&
884 PARA_HASH3=$(git rev-parse --verify HEAD) &&
885 git merge -m "merge HASH4 and PARA_HASH3" "$HASH4" &&
886 PARA_HASH4=$(git rev-parse --verify HEAD) &&
887 add_line_into_file "5(para): add line on parallel branch" dir1/file1 &&
888 PARA_HASH5=$(git rev-parse --verify HEAD) &&
889 add_line_into_file "6(para): add line on parallel branch" dir2/file2 &&
890 PARA_HASH6=$(git rev-parse --verify HEAD) &&
891 git merge -m "merge HASH7 and PARA_HASH6" "$HASH7" &&
892 PARA_HASH7=$(git rev-parse --verify HEAD)
893 '
894
895 test_expect_success 'restricting bisection on one dir' '
896 git bisect reset &&
897 git bisect start HEAD $HASH1 -- dir1 &&
898 para1=$(git rev-parse --verify HEAD) &&
899 test "$para1" = "$PARA_HASH1" &&
900 git bisect bad > my_bisect_log.txt &&
901 test_grep "$PARA_HASH1 is the first '\''bad'\'' commit" my_bisect_log.txt
902 '
903
904 test_expect_success 'restricting bisection on one dir and a file' '
905 git bisect reset &&
906 git bisect start HEAD $HASH1 -- dir1 hello &&
907 para4=$(git rev-parse --verify HEAD) &&
908 test "$para4" = "$PARA_HASH4" &&
909 git bisect bad &&
910 hash3=$(git rev-parse --verify HEAD) &&
911 test "$hash3" = "$HASH3" &&
912 git bisect good &&
913 hash4=$(git rev-parse --verify HEAD) &&
914 test "$hash4" = "$HASH4" &&
915 git bisect good &&
916 para1=$(git rev-parse --verify HEAD) &&
917 test "$para1" = "$PARA_HASH1" &&
918 git bisect good > my_bisect_log.txt &&
919 test_grep "$PARA_HASH4 is the first '\''bad'\'' commit" my_bisect_log.txt
920 '
921
922 test_expect_success 'skipping away from skipped commit' '
923 git bisect start $PARA_HASH7 $HASH1 &&
924 para4=$(git rev-parse --verify HEAD) &&
925 test "$para4" = "$PARA_HASH4" &&
926 git bisect skip &&
927 hash7=$(git rev-parse --verify HEAD) &&
928 test "$hash7" = "$HASH7" &&
929 git bisect skip &&
930 para3=$(git rev-parse --verify HEAD) &&
931 test "$para3" = "$PARA_HASH3"
932 '
933
934 test_expect_success 'erroring out when using bad path arguments' '
935 test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt &&
936 test_grep "bad path arguments" error.txt
937 '
938
939 test_expect_success 'test bisection on bare repo - --no-checkout specified' '
940 git clone --bare . bare.nocheckout &&
941 (
942 cd bare.nocheckout &&
943 git bisect start --no-checkout &&
944 git bisect good $HASH1 &&
945 git bisect bad $HASH4 &&
946 git bisect run eval \
947 "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
948 >../nocheckout.log
949 ) &&
950 test_grep "$HASH3 is the first '\''bad'\'' commit" nocheckout.log
951 '
952
953
954 test_expect_success 'test bisection on bare repo - --no-checkout defaulted' '
955 git clone --bare . bare.defaulted &&
956 (
957 cd bare.defaulted &&
958 git bisect start &&
959 git bisect good $HASH1 &&
960 git bisect bad $HASH4 &&
961 git bisect run eval \
962 "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
963 >../defaulted.log
964 ) &&
965 test_grep "$HASH3 is the first '\''bad'\'' commit" defaulted.log
966 '
967
968 #
969 # This creates a broken branch which cannot be checked out because
970 # the tree created has been deleted.
971 #
972 # H1-H2-H3-H4-H5-H6-H7 <--other
973 # \
974 # S5-S6'-S7'-S8'-S9 <--broken
975 #
976 # Commits marked with ' have a missing tree.
977 #
978 test_expect_success 'broken branch creation' '
979 git bisect reset &&
980 git checkout -b broken $HASH4 &&
981 git tag BROKEN_HASH4 $HASH4 &&
982 add_line_into_file "5(broken): first line on a broken branch" hello2 &&
983 git tag BROKEN_HASH5 &&
984 mkdir missing &&
985 :> missing/MISSING &&
986 git add missing/MISSING &&
987 git commit -m "6(broken): Added file that will be deleted" &&
988 git tag BROKEN_HASH6 &&
989 deleted=$(git rev-parse --verify HEAD:missing) &&
990 add_line_into_file "7(broken): second line on a broken branch" hello2 &&
991 git tag BROKEN_HASH7 &&
992 add_line_into_file "8(broken): third line on a broken branch" hello2 &&
993 git tag BROKEN_HASH8 &&
994 git rm missing/MISSING &&
995 git commit -m "9(broken): Remove missing file" &&
996 git tag BROKEN_HASH9 &&
997 rm .git/objects/$(test_oid_to_path $deleted)
998 '
999
1000 echo "" > expected.ok
1001 cat > expected.missing-tree.default <<EOF
1002 fatal: unable to read tree ($deleted)
1003 EOF
1004
1005 test_expect_success 'bisect fails if tree is broken on start commit' '
1006 git bisect reset &&
1007 test_must_fail git bisect start BROKEN_HASH7 BROKEN_HASH4 2>error.txt &&
1008 test_cmp expected.missing-tree.default error.txt
1009 '
1010
1011 test_expect_success 'bisect fails if tree is broken on trial commit' '
1012 git bisect reset &&
1013 test_must_fail git bisect start BROKEN_HASH9 BROKEN_HASH4 2>error.txt &&
1014 git reset --hard broken &&
1015 git checkout broken &&
1016 test_cmp expected.missing-tree.default error.txt
1017 '
1018
1019 check_same()
1020 {
1021 echo "Checking $1 is the same as $2" &&
1022 test_cmp_rev "$1" "$2"
1023 }
1024
1025 test_expect_success 'bisect: --no-checkout - start commit bad' '
1026 git bisect reset &&
1027 git bisect start BROKEN_HASH7 BROKEN_HASH4 --no-checkout &&
1028 check_same BROKEN_HASH6 BISECT_HEAD &&
1029 git bisect reset
1030 '
1031
1032 test_expect_success 'bisect: --no-checkout - trial commit bad' '
1033 git bisect reset &&
1034 git bisect start broken BROKEN_HASH4 --no-checkout &&
1035 check_same BROKEN_HASH6 BISECT_HEAD &&
1036 git bisect reset
1037 '
1038
1039 test_expect_success 'bisect: --no-checkout - target before breakage' '
1040 git bisect reset &&
1041 git bisect start broken BROKEN_HASH4 --no-checkout &&
1042 check_same BROKEN_HASH6 BISECT_HEAD &&
1043 git bisect bad BISECT_HEAD &&
1044 check_same BROKEN_HASH5 BISECT_HEAD &&
1045 git bisect bad BISECT_HEAD &&
1046 check_same BROKEN_HASH5 bisect/bad &&
1047 git bisect reset
1048 '
1049
1050 test_expect_success 'bisect: --no-checkout - target in breakage' '
1051 git bisect reset &&
1052 git bisect start broken BROKEN_HASH4 --no-checkout &&
1053 check_same BROKEN_HASH6 BISECT_HEAD &&
1054 git bisect bad BISECT_HEAD &&
1055 check_same BROKEN_HASH5 BISECT_HEAD &&
1056 test_must_fail git bisect good BISECT_HEAD &&
1057 check_same BROKEN_HASH6 bisect/bad &&
1058 git bisect reset
1059 '
1060
1061 test_expect_success 'bisect: --no-checkout - target after breakage' '
1062 git bisect reset &&
1063 git bisect start broken BROKEN_HASH4 --no-checkout &&
1064 check_same BROKEN_HASH6 BISECT_HEAD &&
1065 git bisect good BISECT_HEAD &&
1066 check_same BROKEN_HASH8 BISECT_HEAD &&
1067 test_must_fail git bisect good BISECT_HEAD &&
1068 check_same BROKEN_HASH9 bisect/bad &&
1069 git bisect reset
1070 '
1071
1072 test_expect_success 'bisect: demonstrate identification of damage boundary' "
1073 git bisect reset &&
1074 git checkout broken &&
1075 git bisect start broken main --no-checkout &&
1076 test_must_fail git bisect run \"\$SHELL_PATH\" -c '
1077 GOOD=\$(git for-each-ref \"--format=%(objectname)\" refs/bisect/good-*) &&
1078 git rev-list --objects BISECT_HEAD --not \$GOOD >tmp.\$\$ &&
1079 git pack-objects --stdout >/dev/null < tmp.\$\$
1080 rc=\$?
1081 rm -f tmp.\$\$
1082 test \$rc = 0' &&
1083 check_same BROKEN_HASH6 bisect/bad &&
1084 git bisect reset
1085 "
1086
1087 cat > expected.bisect-log <<EOF
1088 # bad: [$HASH4] Add <4: Ciao for now> into <hello>.
1089 # good: [$HASH2] Add <2: A new day for git> into <hello>.
1090 git bisect start '$HASH4' '$HASH2'
1091 # good: [$HASH3] Add <3: Another new day for git> into <hello>.
1092 git bisect good $HASH3
1093 # first 'bad' commit: [$HASH4] Add <4: Ciao for now> into <hello>.
1094 EOF
1095
1096 test_expect_success 'bisect log: successful result' '
1097 git bisect reset &&
1098 git bisect start $HASH4 $HASH2 &&
1099 git bisect good &&
1100 git bisect log >bisect-log.txt &&
1101 test_cmp expected.bisect-log bisect-log.txt &&
1102 git bisect reset
1103 '
1104
1105 cat > expected.bisect-skip-log <<EOF
1106 # bad: [$HASH4] Add <4: Ciao for now> into <hello>.
1107 # good: [$HASH2] Add <2: A new day for git> into <hello>.
1108 git bisect start '$HASH4' '$HASH2'
1109 # skip: [$HASH3] Add <3: Another new day for git> into <hello>.
1110 git bisect skip $HASH3
1111 # only skipped commits left to test
1112 # possible first 'bad' commit: [$HASH4] Add <4: Ciao for now> into <hello>.
1113 # possible first 'bad' commit: [$HASH3] Add <3: Another new day for git> into <hello>.
1114 EOF
1115
1116 test_expect_success 'bisect log: only skip commits left' '
1117 git bisect reset &&
1118 git bisect start $HASH4 $HASH2 &&
1119 test_must_fail git bisect skip &&
1120 git bisect log >bisect-skip-log.txt &&
1121 test_cmp expected.bisect-skip-log bisect-skip-log.txt &&
1122 git bisect reset
1123 '
1124
1125 test_expect_success '"git bisect bad HEAD" behaves as "git bisect bad"' '
1126 git checkout parallel &&
1127 git bisect start HEAD $HASH1 &&
1128 git bisect good HEAD &&
1129 git bisect bad HEAD &&
1130 test "$HASH6" = $(git rev-parse --verify HEAD) &&
1131 git bisect reset
1132 '
1133
1134 test_expect_success 'bisect starts with only one new' '
1135 git bisect reset &&
1136 git bisect start &&
1137 git bisect new $HASH4 &&
1138 git bisect next
1139 '
1140
1141 test_expect_success 'bisect does not start with only one old' '
1142 git bisect reset &&
1143 git bisect start &&
1144 git bisect old $HASH1 &&
1145 test_must_fail git bisect next
1146 '
1147
1148 test_expect_success 'bisect start with one new and old' '
1149 git bisect reset &&
1150 git bisect start &&
1151 git bisect old $HASH1 &&
1152 git bisect new $HASH4 &&
1153 git bisect new &&
1154 git bisect new >bisect_result &&
1155 test_grep "$HASH2 is the first '\''new'\'' commit" bisect_result &&
1156 git bisect log >log_to_replay.txt &&
1157 git bisect reset
1158 '
1159
1160 test_expect_success 'bisect replay with old and new' '
1161 git bisect replay log_to_replay.txt >bisect_result &&
1162 test_grep "$HASH2 is the first '\''new'\'' commit" bisect_result &&
1163 git bisect reset
1164 '
1165
1166 test_expect_success 'bisect replay with CRLF log' '
1167 append_cr <log_to_replay.txt >log_to_replay_crlf.txt &&
1168 git bisect replay log_to_replay_crlf.txt >bisect_result_crlf &&
1169 test_grep "$HASH2 is the first '\''new'\'' commit" bisect_result_crlf &&
1170 git bisect reset
1171 '
1172
1173 test_expect_success 'bisect cannot mix old/new and good/bad' '
1174 git bisect start &&
1175 git bisect bad $HASH4 &&
1176 test_must_fail git bisect old $HASH1
1177 '
1178
1179 test_expect_success 'bisect terms needs 0 or 1 argument' '
1180 git bisect reset &&
1181 test_must_fail git bisect terms only-one &&
1182 test_must_fail git bisect terms 1 2 &&
1183 test_must_fail git bisect terms 2>actual &&
1184 echo "error: no terms defined" >expected &&
1185 test_cmp expected actual
1186 '
1187
1188 test_expect_success 'bisect terms shows good/bad after start' '
1189 git bisect reset &&
1190 git bisect start HEAD $HASH1 &&
1191 git bisect terms --term-good >actual &&
1192 echo good >expected &&
1193 test_cmp expected actual &&
1194 git bisect terms --term-bad >actual &&
1195 echo bad >expected &&
1196 test_cmp expected actual
1197 '
1198
1199 test_expect_success 'bisect start with one term1 and term2' '
1200 git bisect reset &&
1201 git bisect start --term-old term2 --term-new term1 >bisect_result &&
1202 test_grep "status: waiting for both '\''term2'\'' and '\''term1'\'' commits" bisect_result &&
1203 git bisect term2 $HASH1 >bisect_result &&
1204 test_grep "status: waiting for '\''term1'\'' commit, 1 '\''term2'\'' commit known" bisect_result &&
1205 git bisect term1 $HASH4 &&
1206 git bisect term1 &&
1207 git bisect term1 >bisect_result &&
1208 test_grep "$HASH2 is the first '\''term1'\'' commit" bisect_result &&
1209 git bisect log >log_to_replay.txt &&
1210 git bisect reset
1211 '
1212
1213 test_expect_success 'bogus command does not start bisect' '
1214 git bisect reset &&
1215 test_must_fail git bisect --bisect-terms 1 2 2>out &&
1216 test_grep ! "You need to start" out &&
1217 test_must_fail git bisect --bisect-terms 2>out &&
1218 test_grep ! "You need to start" out &&
1219 test_grep "git bisect.*visualize" out &&
1220 git bisect reset
1221 '
1222
1223 test_expect_success 'bisect replay with term1 and term2' '
1224 git bisect replay log_to_replay.txt >bisect_result &&
1225 test_grep "$HASH2 is the first '\''term1'\'' commit" bisect_result &&
1226 git bisect reset
1227 '
1228
1229 test_expect_success 'bisect run term1 term2' '
1230 git bisect reset &&
1231 git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
1232 git bisect term1 &&
1233 git bisect run false >bisect_result &&
1234 test_grep "bisect found first '\''term1'\'' commit" bisect_result &&
1235 git bisect log >log_to_replay.txt &&
1236 git bisect reset
1237 '
1238
1239 test_expect_success 'bisect start term1 term2' '
1240 git bisect reset &&
1241 git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
1242 git bisect term1 &&
1243 git bisect term1 >bisect_result &&
1244 test_grep "$HASH2 is the first '\''term1'\'' commit" bisect_result &&
1245 git bisect log >log_to_replay.txt &&
1246 git bisect reset
1247 '
1248
1249 test_expect_success 'bisect cannot mix terms' '
1250 git bisect reset &&
1251 git bisect start --term-good term1 --term-bad term2 $HASH4 $HASH1 &&
1252 test_must_fail git bisect a &&
1253 test_must_fail git bisect b &&
1254 test_must_fail git bisect bad &&
1255 test_must_fail git bisect good &&
1256 test_must_fail git bisect new &&
1257 test_must_fail git bisect old
1258 '
1259
1260 test_expect_success 'bisect terms rejects invalid terms' '
1261 git bisect reset &&
1262 test_must_fail git bisect start --term-good &&
1263 test_must_fail git bisect start --term-good invalid..term &&
1264 test_must_fail git bisect start --term-bad &&
1265 test_must_fail git bisect terms --term-bad invalid..term &&
1266 test_must_fail git bisect terms --term-good bad &&
1267 test_must_fail git bisect terms --term-good old &&
1268 test_must_fail git bisect terms --term-good skip &&
1269 test_must_fail git bisect terms --term-good reset &&
1270 test_path_is_missing .git/BISECT_TERMS
1271 '
1272
1273 test_expect_success 'bisect start --term-* does store terms' '
1274 git bisect reset &&
1275 git bisect start --term-bad=one --term-good=two &&
1276 git bisect terms >actual &&
1277 cat <<-EOF >expected &&
1278 Your current terms are '\''two'\'' for the old state
1279 and '\''one'\'' for the new state.
1280 EOF
1281 test_cmp expected actual &&
1282 git bisect terms --term-bad >actual &&
1283 echo one >expected &&
1284 test_cmp expected actual &&
1285 git bisect terms --term-good >actual &&
1286 echo two >expected &&
1287 test_cmp expected actual
1288 '
1289
1290 test_expect_success 'bisect start takes options and revs in any order' '
1291 git bisect reset &&
1292 git bisect start --term-good one $HASH4 \
1293 --term-good two --term-bad bad-term \
1294 $HASH1 --term-good three -- &&
1295 (git bisect terms --term-bad && git bisect terms --term-good) >actual &&
1296 printf "%s\n%s\n" bad-term three >expected &&
1297 test_cmp expected actual
1298 '
1299
1300 # Bisect is started with --term-new and --term-old arguments,
1301 # then skip. The HEAD should be changed.
1302 test_expect_success 'bisect skip works with --term*' '
1303 git bisect reset &&
1304 git bisect start --term-new=fixed --term-old=unfixed HEAD $HASH1 &&
1305 hash_skipped_from=$(git rev-parse --verify HEAD) &&
1306 git bisect skip &&
1307 hash_skipped_to=$(git rev-parse --verify HEAD) &&
1308 test "$hash_skipped_from" != "$hash_skipped_to"
1309 '
1310
1311 test_expect_success 'git bisect reset cleans bisection state properly' '
1312 git bisect reset &&
1313 git bisect start &&
1314 git bisect good $HASH1 &&
1315 git bisect bad $HASH4 &&
1316 git bisect reset &&
1317 test -z "$(git for-each-ref "refs/bisect/*")" &&
1318 test_ref_missing BISECT_EXPECTED_REV &&
1319 test_path_is_missing ".git/BISECT_ANCESTORS_OK" &&
1320 test_path_is_missing ".git/BISECT_LOG" &&
1321 test_path_is_missing ".git/BISECT_RUN" &&
1322 test_path_is_missing ".git/BISECT_TERMS" &&
1323 test_path_is_missing ".git/BISECT_HEAD" &&
1324 test_path_is_missing ".git/BISECT_START"
1325 '
1326
1327 test_expect_success 'bisect handles annotated tags' '
1328 test_commit commit-one &&
1329 git tag -m foo tag-one &&
1330 test_commit commit-two &&
1331 git tag -m foo tag-two &&
1332 git bisect start &&
1333 git bisect good tag-one &&
1334 git bisect bad tag-two >output &&
1335 bad=$(git rev-parse --verify tag-two^{commit}) &&
1336 test_grep "$bad is the first '\''bad'\'' commit" output
1337 '
1338
1339 test_expect_success 'bisect run fails with exit code equals or greater than 128' '
1340 write_script test_script.sh <<-\EOF &&
1341 exit 128
1342 EOF
1343 test_must_fail git bisect run ./test_script.sh &&
1344 write_script test_script.sh <<-\EOF &&
1345 exit 255
1346 EOF
1347 test_must_fail git bisect run ./test_script.sh
1348 '
1349
1350 test_expect_success 'bisect visualize with a filename with dash and space' '
1351 echo "My test line" >>"./-hello 2" &&
1352 git add -- "./-hello 2" &&
1353 git commit --quiet -m "Add test line" -- "./-hello 2" &&
1354 git bisect visualize -p -- "-hello 2"
1355 '
1356
1357 test_expect_success 'bisect state output with multiple good commits' '
1358 git bisect reset &&
1359 git bisect start >output &&
1360 test_grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
1361 git bisect log >output &&
1362 test_grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
1363 git bisect good "$HASH1" >output &&
1364 test_grep "waiting for '\''bad'\'' commit, 1 '\''good'\'' commit known" output &&
1365 git bisect log >output &&
1366 test_grep "waiting for '\''bad'\'' commit, 1 '\''good'\'' commit known" output &&
1367 git bisect good "$HASH2" >output &&
1368 test_grep "waiting for '\''bad'\'' commit, 2 '\''good'\'' commits known" output &&
1369 git bisect log >output &&
1370 test_grep "waiting for '\''bad'\'' commit, 2 '\''good'\'' commits known" output
1371 '
1372
1373 test_expect_success 'bisect state output with bad commit' '
1374 git bisect reset &&
1375 git bisect start >output &&
1376 test_grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
1377 git bisect log >output &&
1378 test_grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
1379 git bisect bad "$HASH4" >output &&
1380 test_grep -F "waiting for '\''good'\'' commit(s), '\''bad'\'' commit known" output &&
1381 git bisect log >output &&
1382 test_grep -F "waiting for '\''good'\'' commit(s), '\''bad'\'' commit known" output
1383 '
1384
1385 test_expect_success 'verify correct error message' '
1386 git bisect reset &&
1387 git bisect start $HASH4 $HASH1 &&
1388 write_script test_script.sh <<-\EOF &&
1389 rm .git/BISECT*
1390 EOF
1391 test_must_fail git bisect run ./test_script.sh 2>error &&
1392 test_grep "git bisect good.*exited with error code" error
1393 '
1394
1395 test_done