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