Merge branch 'rj/cygwin-has-dev-tty'
[git/gitster.git] / t / t7201-co.sh
blob2d984eb4c6a167c3c0f1e072a66aa90fe7b15660
1 #!/bin/sh
3 # Copyright (c) 2006 Junio C Hamano
6 test_description='git checkout tests.
8 Creates main, forks renamer and side branches from it.
9 Test switching across them.
11 ! [main] Initial A one, A two
12 * [renamer] Renamer R one->uno, M two
13 ! [side] Side M one, D two, A three
14 ! [simple] Simple D one, M two
15 ----
16 + [simple] Simple D one, M two
17 + [side] Side M one, D two, A three
18 * [renamer] Renamer R one->uno, M two
19 +*++ [main] Initial A one, A two
23 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
24 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
26 TEST_PASSES_SANITIZE_LEAK=true
27 . ./test-lib.sh
29 test_tick
31 fill () {
32 for i
34 echo "$i"
35 done
39 test_expect_success setup '
40 fill x y z >same &&
41 fill 1 2 3 4 5 6 7 8 >one &&
42 fill a b c d e >two &&
43 git add same one two &&
44 git commit -m "Initial A one, A two" &&
46 git checkout -b renamer &&
47 rm -f one &&
48 fill 1 3 4 5 6 7 8 >uno &&
49 git add uno &&
50 fill a b c d e f >two &&
51 git commit -a -m "Renamer R one->uno, M two" &&
53 git checkout -b side main &&
54 fill 1 2 3 4 5 6 7 >one &&
55 fill A B C D E >three &&
56 rm -f two &&
57 git update-index --add --remove one two three &&
58 git commit -m "Side M one, D two, A three" &&
60 git checkout -b simple main &&
61 rm -f one &&
62 fill a c e >two &&
63 git commit -a -m "Simple D one, M two" &&
65 git checkout main
68 test_expect_success 'checkout from non-existing branch' '
69 git checkout -b delete-me main &&
70 git update-ref -d --no-deref refs/heads/delete-me &&
71 test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
72 git checkout main &&
73 test refs/heads/main = "$(git symbolic-ref HEAD)"
76 test_expect_success 'checkout with dirty tree without -m' '
77 fill 0 1 2 3 4 5 6 7 8 >one &&
78 if git checkout side
79 then
80 echo Not happy
81 false
82 else
83 echo "happy - failed correctly"
87 test_expect_success 'checkout with unrelated dirty tree without -m' '
88 git checkout -f main &&
89 fill 0 1 2 3 4 5 6 7 8 >same &&
90 cp same kept &&
91 git checkout side >messages &&
92 test_cmp same kept &&
93 printf "M\t%s\n" same >messages.expect &&
94 test_cmp messages.expect messages
97 test_expect_success 'checkout -m with dirty tree' '
98 git checkout -f main &&
99 git clean -f &&
101 fill 0 1 2 3 4 5 6 7 8 >one &&
102 git checkout -m side >messages &&
104 test "$(git symbolic-ref HEAD)" = "refs/heads/side" &&
106 printf "M\t%s\n" one >expect.messages &&
107 test_cmp expect.messages messages &&
109 fill "M one" "A three" "D two" >expect.main &&
110 git diff --name-status main >current.main &&
111 test_cmp expect.main current.main &&
113 fill "M one" >expect.side &&
114 git diff --name-status side >current.side &&
115 test_cmp expect.side current.side &&
117 git diff --cached >current.index &&
118 test_must_be_empty current.index
121 test_expect_success 'checkout -m with dirty tree, renamed' '
122 git checkout -f main && git clean -f &&
124 fill 1 2 3 4 5 7 8 >one &&
125 if git checkout renamer
126 then
127 echo Not happy
128 false
129 else
130 echo "happy - failed correctly"
131 fi &&
133 git checkout -m renamer &&
134 fill 1 3 4 5 7 8 >expect &&
135 test_cmp expect uno &&
136 ! test -f one &&
137 git diff --cached >current &&
138 test_must_be_empty current
141 test_expect_success 'checkout -m with merge conflict' '
142 git checkout -f main && git clean -f &&
144 fill 1 T 3 4 5 6 S 8 >one &&
145 if git checkout renamer
146 then
147 echo Not happy
148 false
149 else
150 echo "happy - failed correctly"
151 fi &&
153 git checkout -m renamer &&
155 git diff main:one :3:uno |
156 sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current &&
157 fill d2 aT d7 aS >expect &&
158 test_cmp expect current &&
159 git diff --cached two >current &&
160 test_must_be_empty current
163 test_expect_success 'format of merge conflict from checkout -m' '
164 git checkout -f main &&
165 git clean -f &&
167 fill b d >two &&
168 git checkout -m simple &&
170 git ls-files >current &&
171 fill same two two two >expect &&
172 test_cmp expect current &&
174 cat <<-EOF >expect &&
175 <<<<<<< simple
179 =======
182 >>>>>>> local
184 test_cmp expect two
187 test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
188 git checkout -f main &&
189 git reset --hard &&
190 git clean -f &&
192 fill b d >two &&
193 git checkout --merge --conflict=diff3 simple &&
195 cat <<-EOF >expect &&
196 <<<<<<< simple
200 ||||||| main
206 =======
209 >>>>>>> local
211 test_cmp expect two
214 test_expect_success 'switch to another branch while carrying a deletion' '
215 git checkout -f main &&
216 git reset --hard &&
217 git clean -f &&
218 git rm two &&
220 test_must_fail git checkout simple 2>errs &&
221 test_grep overwritten errs &&
223 test_must_fail git read-tree --quiet -m -u HEAD simple 2>errs &&
224 test_must_be_empty errs
227 test_expect_success 'checkout to detach HEAD (with advice declined)' '
228 git config advice.detachedHead false &&
229 rev=$(git rev-parse --short renamer^) &&
230 git checkout -f renamer &&
231 git clean -f &&
232 git checkout renamer^ 2>messages &&
233 test_grep "HEAD is now at $rev" messages &&
234 test_line_count = 1 messages &&
235 H=$(git rev-parse --verify HEAD) &&
236 M=$(git show-ref -s --verify refs/heads/main) &&
237 test "z$H" = "z$M" &&
238 if git symbolic-ref HEAD >/dev/null 2>&1
239 then
240 echo "OOPS, HEAD is still symbolic???"
241 false
242 else
243 : happy
247 test_expect_success 'checkout to detach HEAD' '
248 git config advice.detachedHead true &&
249 rev=$(git rev-parse --short renamer^) &&
250 git checkout -f renamer &&
251 git clean -f &&
252 git checkout renamer^ 2>messages &&
253 grep "HEAD is now at $rev" messages &&
254 test_line_count -gt 1 messages &&
255 H=$(git rev-parse --verify HEAD) &&
256 M=$(git show-ref -s --verify refs/heads/main) &&
257 test "z$H" = "z$M" &&
258 if git symbolic-ref HEAD >/dev/null 2>&1
259 then
260 echo "OOPS, HEAD is still symbolic???"
261 false
262 else
263 : happy
267 test_expect_success 'checkout to detach HEAD with branchname^' '
268 git checkout -f main &&
269 git clean -f &&
270 git checkout renamer^ &&
271 H=$(git rev-parse --verify HEAD) &&
272 M=$(git show-ref -s --verify refs/heads/main) &&
273 test "z$H" = "z$M" &&
274 if git symbolic-ref HEAD >/dev/null 2>&1
275 then
276 echo "OOPS, HEAD is still symbolic???"
277 false
278 else
279 : happy
283 test_expect_success 'checkout to detach HEAD with :/message' '
284 git checkout -f main &&
285 git clean -f &&
286 git checkout ":/Initial" &&
287 H=$(git rev-parse --verify HEAD) &&
288 M=$(git show-ref -s --verify refs/heads/main) &&
289 test "z$H" = "z$M" &&
290 if git symbolic-ref HEAD >/dev/null 2>&1
291 then
292 echo "OOPS, HEAD is still symbolic???"
293 false
294 else
295 : happy
299 test_expect_success 'checkout to detach HEAD with HEAD^0' '
300 git checkout -f main &&
301 git clean -f &&
302 git checkout HEAD^0 &&
303 H=$(git rev-parse --verify HEAD) &&
304 M=$(git show-ref -s --verify refs/heads/main) &&
305 test "z$H" = "z$M" &&
306 if git symbolic-ref HEAD >/dev/null 2>&1
307 then
308 echo "OOPS, HEAD is still symbolic???"
309 false
310 else
311 : happy
315 test_expect_success 'checkout with ambiguous tag/branch names' '
316 git tag both side &&
317 git branch both main &&
318 git reset --hard &&
319 git checkout main &&
321 git checkout both &&
322 H=$(git rev-parse --verify HEAD) &&
323 M=$(git show-ref -s --verify refs/heads/main) &&
324 test "z$H" = "z$M" &&
325 name=$(git symbolic-ref HEAD 2>/dev/null) &&
326 test "z$name" = zrefs/heads/both
329 test_expect_success 'checkout with ambiguous tag/branch names' '
330 git reset --hard &&
331 git checkout main &&
333 git tag frotz side &&
334 git branch frotz main &&
335 git reset --hard &&
336 git checkout main &&
338 git checkout tags/frotz &&
339 H=$(git rev-parse --verify HEAD) &&
340 S=$(git show-ref -s --verify refs/heads/side) &&
341 test "z$H" = "z$S" &&
342 if name=$(git symbolic-ref HEAD 2>/dev/null)
343 then
344 echo "Bad -- should have detached"
345 false
346 else
347 : happy
351 test_expect_success 'switch branches while in subdirectory' '
352 git reset --hard &&
353 git checkout main &&
355 mkdir subs &&
356 git -C subs checkout side &&
357 ! test -f subs/one &&
358 rm -fr subs
361 test_expect_success 'checkout specific path while in subdirectory' '
362 git reset --hard &&
363 git checkout side &&
364 mkdir subs &&
365 >subs/bero &&
366 git add subs/bero &&
367 git commit -m "add subs/bero" &&
369 git checkout main &&
370 mkdir -p subs &&
371 git -C subs checkout side -- bero &&
372 test -f subs/bero
375 test_expect_success 'checkout w/--track sets up tracking' '
376 git config branch.autosetupmerge false &&
377 git checkout main &&
378 git checkout --track -b track1 &&
379 test "$(git config branch.track1.remote)" &&
380 test "$(git config branch.track1.merge)"
383 test_expect_success 'checkout w/autosetupmerge=always sets up tracking' '
384 test_when_finished git config branch.autosetupmerge false &&
385 git config branch.autosetupmerge always &&
386 git checkout main &&
387 git checkout -b track2 &&
388 test "$(git config branch.track2.remote)" &&
389 test "$(git config branch.track2.merge)"
392 test_expect_success 'checkout w/--track from non-branch HEAD fails' '
393 git checkout main^0 &&
394 test_must_fail git symbolic-ref HEAD &&
395 test_must_fail git checkout --track -b track &&
396 test_must_fail git rev-parse --verify track &&
397 test_must_fail git symbolic-ref HEAD &&
398 test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
401 test_expect_success 'checkout w/--track from tag fails' '
402 git checkout main^0 &&
403 test_must_fail git symbolic-ref HEAD &&
404 test_must_fail git checkout --track -b track frotz &&
405 test_must_fail git rev-parse --verify track &&
406 test_must_fail git symbolic-ref HEAD &&
407 test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
410 test_expect_success 'detach a symbolic link HEAD' '
411 git checkout main &&
412 git config --bool core.prefersymlinkrefs yes &&
413 git checkout side &&
414 git checkout main &&
415 it=$(git symbolic-ref HEAD) &&
416 test "z$it" = zrefs/heads/main &&
417 here=$(git rev-parse --verify refs/heads/main) &&
418 git checkout side^ &&
419 test "z$(git rev-parse --verify refs/heads/main)" = "z$here"
422 test_expect_success 'checkout with --track fakes a sensible -b <name>' '
423 git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
424 git update-ref refs/remotes/origin/koala/bear renamer &&
426 git checkout --track origin/koala/bear &&
427 test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
428 test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
430 git checkout main && git branch -D koala/bear &&
432 git checkout --track refs/remotes/origin/koala/bear &&
433 test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
434 test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
436 git checkout main && git branch -D koala/bear &&
438 git checkout --track remotes/origin/koala/bear &&
439 test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
440 test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
443 test_expect_success 'checkout with --track, but without -b, fails with too short tracked name' '
444 test_must_fail git checkout --track renamer
447 setup_conflicting_index () {
448 rm -f .git/index &&
449 O=$(echo original | git hash-object -w --stdin) &&
450 A=$(echo ourside | git hash-object -w --stdin) &&
451 B=$(echo theirside | git hash-object -w --stdin) &&
453 echo "100644 $A 0 fild" &&
454 echo "100644 $O 1 file" &&
455 echo "100644 $A 2 file" &&
456 echo "100644 $B 3 file" &&
457 echo "100644 $A 0 filf"
458 ) | git update-index --index-info
461 test_expect_success 'checkout an unmerged path should fail' '
462 setup_conflicting_index &&
463 echo "none of the above" >sample &&
464 cat sample >fild &&
465 cat sample >file &&
466 cat sample >filf &&
467 test_must_fail git checkout fild file filf &&
468 test_cmp sample fild &&
469 test_cmp sample filf &&
470 test_cmp sample file
473 test_expect_success 'checkout with an unmerged path can be ignored' '
474 setup_conflicting_index &&
475 echo "none of the above" >sample &&
476 echo ourside >expect &&
477 cat sample >fild &&
478 cat sample >file &&
479 cat sample >filf &&
480 git checkout -f fild file filf &&
481 test_cmp expect fild &&
482 test_cmp expect filf &&
483 test_cmp sample file
486 test_expect_success 'checkout unmerged stage' '
487 setup_conflicting_index &&
488 echo "none of the above" >sample &&
489 echo ourside >expect &&
490 cat sample >fild &&
491 cat sample >file &&
492 cat sample >filf &&
493 git checkout --ours . &&
494 test_cmp expect fild &&
495 test_cmp expect filf &&
496 test_cmp expect file &&
497 git checkout --theirs file &&
498 test ztheirside = "z$(cat file)"
501 test_expect_success 'checkout --ours is incompatible with switching' '
502 test_must_fail git checkout --ours 2>error &&
503 test_grep "needs the paths to check out" error &&
505 test_must_fail git checkout --ours HEAD 2>error &&
506 test_grep "cannot be used with switching" error &&
508 test_must_fail git checkout --ours main 2>error &&
509 test_grep "cannot be used with switching" error &&
511 git checkout --ours file
514 test_expect_success 'checkout path with --merge from tree-ish is a no-no' '
515 setup_conflicting_index &&
516 test_must_fail git checkout -m HEAD -- file
519 test_expect_success 'checkout with --merge' '
520 setup_conflicting_index &&
521 echo "none of the above" >sample &&
522 echo ourside >expect &&
523 cat sample >fild &&
524 cat sample >file &&
525 cat sample >filf &&
526 git checkout -m -- fild file filf &&
528 echo "<<<<<<< ours" &&
529 echo ourside &&
530 echo "=======" &&
531 echo theirside &&
532 echo ">>>>>>> theirs"
533 ) >merged &&
534 test_cmp expect fild &&
535 test_cmp expect filf &&
536 test_cmp merged file
539 test_expect_success 'checkout -m works after (mistaken) resolution' '
540 setup_conflicting_index &&
541 echo "none of the above" >sample &&
542 cat sample >fild &&
543 cat sample >file &&
544 cat sample >filf &&
545 # resolve to something
546 git add file &&
547 git checkout --merge -- fild file filf &&
549 echo "<<<<<<< ours" &&
550 echo ourside &&
551 echo "=======" &&
552 echo theirside &&
553 echo ">>>>>>> theirs"
554 } >merged &&
555 test_cmp expect fild &&
556 test_cmp expect filf &&
557 test_cmp merged file
560 test_expect_success 'checkout -m works after (mistaken) resolution to remove' '
561 setup_conflicting_index &&
562 echo "none of the above" >sample &&
563 cat sample >fild &&
564 cat sample >file &&
565 cat sample >filf &&
566 # resolve to remove
567 git rm file &&
568 git checkout --merge -- fild file filf &&
570 echo "<<<<<<< ours" &&
571 echo ourside &&
572 echo "=======" &&
573 echo theirside &&
574 echo ">>>>>>> theirs"
575 } >merged &&
576 test_cmp expect fild &&
577 test_cmp expect filf &&
578 test_cmp merged file
581 test_expect_success 'checkout with --merge, in diff3 -m style' '
582 git config merge.conflictstyle diff3 &&
583 setup_conflicting_index &&
584 echo "none of the above" >sample &&
585 echo ourside >expect &&
586 cat sample >fild &&
587 cat sample >file &&
588 cat sample >filf &&
589 git checkout -m -- fild file filf &&
591 echo "<<<<<<< ours" &&
592 echo ourside &&
593 echo "||||||| base" &&
594 echo original &&
595 echo "=======" &&
596 echo theirside &&
597 echo ">>>>>>> theirs"
598 ) >merged &&
599 test_cmp expect fild &&
600 test_cmp expect filf &&
601 test_cmp merged file
604 test_expect_success 'checkout --conflict=merge, overriding config' '
605 git config merge.conflictstyle diff3 &&
606 setup_conflicting_index &&
607 echo "none of the above" >sample &&
608 echo ourside >expect &&
609 cat sample >fild &&
610 cat sample >file &&
611 cat sample >filf &&
612 git checkout --conflict=merge -- fild file filf &&
614 echo "<<<<<<< ours" &&
615 echo ourside &&
616 echo "=======" &&
617 echo theirside &&
618 echo ">>>>>>> theirs"
619 ) >merged &&
620 test_cmp expect fild &&
621 test_cmp expect filf &&
622 test_cmp merged file
625 test_expect_success 'checkout --conflict=diff3' '
626 test_unconfig merge.conflictstyle &&
627 setup_conflicting_index &&
628 echo "none of the above" >sample &&
629 echo ourside >expect &&
630 cat sample >fild &&
631 cat sample >file &&
632 cat sample >filf &&
633 git checkout --conflict=diff3 -- fild file filf &&
635 echo "<<<<<<< ours" &&
636 echo ourside &&
637 echo "||||||| base" &&
638 echo original &&
639 echo "=======" &&
640 echo theirside &&
641 echo ">>>>>>> theirs"
642 ) >merged &&
643 test_cmp expect fild &&
644 test_cmp expect filf &&
645 test_cmp merged file
648 test_expect_success 'checkout --conflict=diff3 --no-conflict does not merge' '
649 setup_conflicting_index &&
650 echo "none of the above" >expect &&
651 cat expect >fild &&
652 cat expect >file &&
653 test_must_fail git checkout --conflict=diff3 --no-conflict -- fild file 2>err &&
654 test_cmp expect file &&
655 test_cmp expect fild &&
656 echo "error: path ${SQ}file${SQ} is unmerged" >expect &&
657 test_cmp expect err
660 test_expect_success 'checkout --conflict=diff3 --no-merge does not merge' '
661 setup_conflicting_index &&
662 echo "none of the above" >expect &&
663 cat expect >fild &&
664 cat expect >file &&
665 test_must_fail git checkout --conflict=diff3 --no-merge -- fild file 2>err &&
666 test_cmp expect file &&
667 test_cmp expect fild &&
668 echo "error: path ${SQ}file${SQ} is unmerged" >expect &&
669 test_cmp expect err
672 test_expect_success 'checkout --no-merge --conflict=diff3 does merge' '
673 setup_conflicting_index &&
674 echo "none of the above" >fild &&
675 echo "none of the above" >file &&
676 git checkout --no-merge --conflict=diff3 -- fild file &&
677 echo "ourside" >expect &&
678 test_cmp expect fild &&
679 cat >expect <<-\EOF &&
680 <<<<<<< ours
681 ourside
682 ||||||| base
683 original
684 =======
685 theirside
686 >>>>>>> theirs
688 test_cmp expect file
691 test_expect_success 'checkout --merge --conflict=diff3 --no-conflict does merge' '
692 setup_conflicting_index &&
693 echo "none of the above" >fild &&
694 echo "none of the above" >file &&
695 git checkout --merge --conflict=diff3 --no-conflict -- fild file &&
696 echo "ourside" >expect &&
697 test_cmp expect fild &&
698 cat >expect <<-\EOF &&
699 <<<<<<< ours
700 ourside
701 =======
702 theirside
703 >>>>>>> theirs
705 test_cmp expect file
708 test_expect_success 'checkout with invalid conflict style' '
709 test_must_fail git checkout --conflict=bad 2>actual -- file &&
710 echo "error: unknown conflict style ${SQ}bad${SQ}" >expect &&
711 test_cmp expect actual
714 test_expect_success 'failing checkout -b should not break working tree' '
715 git clean -fd && # Remove untracked files in the way
716 git reset --hard main &&
717 git symbolic-ref HEAD refs/heads/main &&
718 test_must_fail git checkout -b renamer side^ &&
719 test $(git symbolic-ref HEAD) = refs/heads/main &&
720 git diff --exit-code &&
721 git diff --cached --exit-code
724 test_expect_success 'switch out of non-branch' '
725 git reset --hard main &&
726 git checkout main^0 &&
727 echo modified >one &&
728 test_must_fail git checkout renamer 2>error.log &&
729 ! grep "^Previous HEAD" error.log
733 echo "#!$SHELL_PATH"
734 cat <<\EOF
735 O=$1 A=$2 B=$3
736 cat "$A" >.tmp
737 exec >"$A"
738 echo '<<<<<<< filfre-theirs'
739 cat "$B"
740 echo '||||||| filfre-common'
741 cat "$O"
742 echo '======='
743 cat ".tmp"
744 echo '>>>>>>> filfre-ours'
745 rm -f .tmp
746 exit 1
748 ) >filfre.sh
749 chmod +x filfre.sh
751 test_expect_success 'custom merge driver with checkout -m' '
752 git reset --hard &&
754 git config merge.filfre.driver "./filfre.sh %O %A %B" &&
755 git config merge.filfre.name "Feel-free merge driver" &&
756 git config merge.filfre.recursive binary &&
757 echo "arm merge=filfre" >.gitattributes &&
759 git checkout -b left &&
760 echo neutral >arm &&
761 git add arm .gitattributes &&
762 test_tick &&
763 git commit -m neutral &&
764 git branch right &&
766 echo left >arm &&
767 test_tick &&
768 git commit -a -m left &&
769 git checkout right &&
771 echo right >arm &&
772 test_tick &&
773 git commit -a -m right &&
775 test_must_fail git merge left &&
777 for t in filfre-common left right
779 grep $t arm || exit 1
780 done
781 ) &&
783 mv arm expect &&
784 git checkout -m arm &&
785 test_cmp expect arm
788 test_expect_success 'tracking info copied with autoSetupMerge=inherit' '
789 git reset --hard main &&
790 # default config does not copy tracking info
791 git checkout -b foo-no-inherit koala/bear &&
792 test_cmp_config "" --default "" branch.foo-no-inherit.remote &&
793 test_cmp_config "" --default "" branch.foo-no-inherit.merge &&
794 # with autoSetupMerge=inherit, we copy tracking info from koala/bear
795 test_config branch.autoSetupMerge inherit &&
796 git checkout -b foo koala/bear &&
797 test_cmp_config origin branch.foo.remote &&
798 test_cmp_config refs/heads/koala/bear branch.foo.merge &&
799 # no tracking info to inherit from main
800 git checkout -b main2 main &&
801 test_cmp_config "" --default "" branch.main2.remote &&
802 test_cmp_config "" --default "" branch.main2.merge
805 test_done