t / t7201-co.shon commit Merge branch 'rr/rebase-autostash-fix' into maint (d9036cd)
   1#!/bin/sh
   2#
   3# Copyright (c) 2006 Junio C Hamano
   4#
   5
   6test_description='git checkout tests.
   7
   8Creates master, forks renamer and side branches from it.
   9Test switching across them.
  10
  11  ! [master] 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  +*++ [master] Initial A one, A two
  20
  21'
  22
  23. ./test-lib.sh
  24
  25test_tick
  26
  27fill () {
  28        for i
  29        do
  30                echo "$i"
  31        done
  32}
  33
  34
  35test_expect_success setup '
  36
  37        fill x y z > same &&
  38        fill 1 2 3 4 5 6 7 8 >one &&
  39        fill a b c d e >two &&
  40        git add same one two &&
  41        git commit -m "Initial A one, A two" &&
  42
  43        git checkout -b renamer &&
  44        rm -f one &&
  45        fill 1 3 4 5 6 7 8 >uno &&
  46        git add uno &&
  47        fill a b c d e f >two &&
  48        git commit -a -m "Renamer R one->uno, M two" &&
  49
  50        git checkout -b side master &&
  51        fill 1 2 3 4 5 6 7 >one &&
  52        fill A B C D E >three &&
  53        rm -f two &&
  54        git update-index --add --remove one two three &&
  55        git commit -m "Side M one, D two, A three" &&
  56
  57        git checkout -b simple master &&
  58        rm -f one &&
  59        fill a c e > two &&
  60        git commit -a -m "Simple D one, M two" &&
  61
  62        git checkout master
  63'
  64
  65test_expect_success "checkout from non-existing branch" '
  66
  67        git checkout -b delete-me master &&
  68        rm .git/refs/heads/delete-me &&
  69        test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
  70        git checkout master &&
  71        test refs/heads/master = "$(git symbolic-ref HEAD)"
  72'
  73
  74test_expect_success "checkout with dirty tree without -m" '
  75
  76        fill 0 1 2 3 4 5 6 7 8 >one &&
  77        if git checkout side
  78        then
  79                echo Not happy
  80                false
  81        else
  82                echo "happy - failed correctly"
  83        fi
  84
  85'
  86
  87test_expect_success "checkout with unrelated dirty tree without -m" '
  88
  89        git checkout -f master &&
  90        fill 0 1 2 3 4 5 6 7 8 >same &&
  91        cp same kept
  92        git checkout side >messages &&
  93        test_cmp same kept
  94        (cat > messages.expect <<EOF
  95M       same
  96EOF
  97) &&
  98        touch messages.expect &&
  99        test_cmp messages.expect messages
 100'
 101
 102test_expect_success "checkout -m with dirty tree" '
 103
 104        git checkout -f master &&
 105        git clean -f &&
 106
 107        fill 0 1 2 3 4 5 6 7 8 >one &&
 108        git checkout -m side > messages &&
 109
 110        test "$(git symbolic-ref HEAD)" = "refs/heads/side" &&
 111
 112        (cat >expect.messages <<EOF
 113M       one
 114EOF
 115) &&
 116        test_cmp expect.messages messages &&
 117
 118        fill "M one" "A three" "D       two" >expect.master &&
 119        git diff --name-status master >current.master &&
 120        test_cmp expect.master current.master &&
 121
 122        fill "M one" >expect.side &&
 123        git diff --name-status side >current.side &&
 124        test_cmp expect.side current.side &&
 125
 126        : >expect.index &&
 127        git diff --cached >current.index &&
 128        test_cmp expect.index current.index
 129'
 130
 131test_expect_success "checkout -m with dirty tree, renamed" '
 132
 133        git checkout -f master && git clean -f &&
 134
 135        fill 1 2 3 4 5 7 8 >one &&
 136        if git checkout renamer
 137        then
 138                echo Not happy
 139                false
 140        else
 141                echo "happy - failed correctly"
 142        fi &&
 143
 144        git checkout -m renamer &&
 145        fill 1 3 4 5 7 8 >expect &&
 146        test_cmp expect uno &&
 147        ! test -f one &&
 148        git diff --cached >current &&
 149        ! test -s current
 150
 151'
 152
 153test_expect_success 'checkout -m with merge conflict' '
 154
 155        git checkout -f master && git clean -f &&
 156
 157        fill 1 T 3 4 5 6 S 8 >one &&
 158        if git checkout renamer
 159        then
 160                echo Not happy
 161                false
 162        else
 163                echo "happy - failed correctly"
 164        fi &&
 165
 166        git checkout -m renamer &&
 167
 168        git diff master:one :3:uno |
 169        sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current &&
 170        fill d2 aT d7 aS >expect &&
 171        test_cmp current expect &&
 172        git diff --cached two >current &&
 173        ! test -s current
 174'
 175
 176test_expect_success 'format of merge conflict from checkout -m' '
 177
 178        git checkout -f master && git clean -f &&
 179
 180        fill b d > two &&
 181        git checkout -m simple &&
 182
 183        git ls-files >current &&
 184        fill same two two two >expect &&
 185        test_cmp current expect &&
 186
 187        cat <<-EOF >expect &&
 188        <<<<<<< simple
 189        a
 190        c
 191        e
 192        =======
 193        b
 194        d
 195        >>>>>>> local
 196        EOF
 197        test_cmp two expect
 198'
 199
 200test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
 201
 202        git checkout -f master && git reset --hard && git clean -f &&
 203
 204        fill b d > two &&
 205        git checkout --merge --conflict=diff3 simple &&
 206
 207        cat <<-EOF >expect &&
 208        <<<<<<< simple
 209        a
 210        c
 211        e
 212        ||||||| master
 213        a
 214        b
 215        c
 216        d
 217        e
 218        =======
 219        b
 220        d
 221        >>>>>>> local
 222        EOF
 223        test_cmp two expect
 224'
 225
 226test_expect_success 'checkout to detach HEAD (with advice declined)' '
 227
 228        git config advice.detachedHead false &&
 229        git checkout -f renamer && git clean -f &&
 230        git checkout renamer^ 2>messages &&
 231        test_i18ngrep "HEAD is now at 7329388" messages &&
 232        test_line_count = 1 messages &&
 233        H=$(git rev-parse --verify HEAD) &&
 234        M=$(git show-ref -s --verify refs/heads/master) &&
 235        test "z$H" = "z$M" &&
 236        if git symbolic-ref HEAD >/dev/null 2>&1
 237        then
 238                echo "OOPS, HEAD is still symbolic???"
 239                false
 240        else
 241                : happy
 242        fi
 243'
 244
 245test_expect_success 'checkout to detach HEAD' '
 246        git config advice.detachedHead true &&
 247        git checkout -f renamer && git clean -f &&
 248        git checkout renamer^ 2>messages &&
 249        test_i18ngrep "HEAD is now at 7329388" messages &&
 250        test_line_count -gt 1 messages &&
 251        H=$(git rev-parse --verify HEAD) &&
 252        M=$(git show-ref -s --verify refs/heads/master) &&
 253        test "z$H" = "z$M" &&
 254        if git symbolic-ref HEAD >/dev/null 2>&1
 255        then
 256                echo "OOPS, HEAD is still symbolic???"
 257                false
 258        else
 259                : happy
 260        fi
 261'
 262
 263test_expect_success 'checkout to detach HEAD with branchname^' '
 264
 265        git checkout -f master && git clean -f &&
 266        git checkout renamer^ &&
 267        H=$(git rev-parse --verify HEAD) &&
 268        M=$(git show-ref -s --verify refs/heads/master) &&
 269        test "z$H" = "z$M" &&
 270        if git symbolic-ref HEAD >/dev/null 2>&1
 271        then
 272                echo "OOPS, HEAD is still symbolic???"
 273                false
 274        else
 275                : happy
 276        fi
 277'
 278
 279test_expect_success 'checkout to detach HEAD with :/message' '
 280
 281        git checkout -f master && git clean -f &&
 282        git checkout ":/Initial" &&
 283        H=$(git rev-parse --verify HEAD) &&
 284        M=$(git show-ref -s --verify refs/heads/master) &&
 285        test "z$H" = "z$M" &&
 286        if git symbolic-ref HEAD >/dev/null 2>&1
 287        then
 288                echo "OOPS, HEAD is still symbolic???"
 289                false
 290        else
 291                : happy
 292        fi
 293'
 294
 295test_expect_success 'checkout to detach HEAD with HEAD^0' '
 296
 297        git checkout -f master && git clean -f &&
 298        git checkout HEAD^0 &&
 299        H=$(git rev-parse --verify HEAD) &&
 300        M=$(git show-ref -s --verify refs/heads/master) &&
 301        test "z$H" = "z$M" &&
 302        if git symbolic-ref HEAD >/dev/null 2>&1
 303        then
 304                echo "OOPS, HEAD is still symbolic???"
 305                false
 306        else
 307                : happy
 308        fi
 309'
 310
 311test_expect_success 'checkout with ambiguous tag/branch names' '
 312
 313        git tag both side &&
 314        git branch both master &&
 315        git reset --hard &&
 316        git checkout master &&
 317
 318        git checkout both &&
 319        H=$(git rev-parse --verify HEAD) &&
 320        M=$(git show-ref -s --verify refs/heads/master) &&
 321        test "z$H" = "z$M" &&
 322        name=$(git symbolic-ref HEAD 2>/dev/null) &&
 323        test "z$name" = zrefs/heads/both
 324
 325'
 326
 327test_expect_success 'checkout with ambiguous tag/branch names' '
 328
 329        git reset --hard &&
 330        git checkout master &&
 331
 332        git tag frotz side &&
 333        git branch frotz master &&
 334        git reset --hard &&
 335        git checkout master &&
 336
 337        git checkout tags/frotz &&
 338        H=$(git rev-parse --verify HEAD) &&
 339        S=$(git show-ref -s --verify refs/heads/side) &&
 340        test "z$H" = "z$S" &&
 341        if name=$(git symbolic-ref HEAD 2>/dev/null)
 342        then
 343                echo "Bad -- should have detached"
 344                false
 345        else
 346                : happy
 347        fi
 348
 349'
 350
 351test_expect_success 'switch branches while in subdirectory' '
 352
 353        git reset --hard &&
 354        git checkout master &&
 355
 356        mkdir subs &&
 357        (
 358                cd subs &&
 359                git checkout side
 360        ) &&
 361        ! test -f subs/one &&
 362        rm -fr subs
 363
 364'
 365
 366test_expect_success 'checkout specific path while in subdirectory' '
 367
 368        git reset --hard &&
 369        git checkout side &&
 370        mkdir subs &&
 371        >subs/bero &&
 372        git add subs/bero &&
 373        git commit -m "add subs/bero" &&
 374
 375        git checkout master &&
 376        mkdir -p subs &&
 377        (
 378                cd subs &&
 379                git checkout side -- bero
 380        ) &&
 381        test -f subs/bero
 382
 383'
 384
 385test_expect_success \
 386    'checkout w/--track sets up tracking' '
 387    git config branch.autosetupmerge false &&
 388    git checkout master &&
 389    git checkout --track -b track1 &&
 390    test "$(git config branch.track1.remote)" &&
 391    test "$(git config branch.track1.merge)"'
 392
 393test_expect_success \
 394    'checkout w/autosetupmerge=always sets up tracking' '
 395    git config branch.autosetupmerge always &&
 396    git checkout master &&
 397    git checkout -b track2 &&
 398    test "$(git config branch.track2.remote)" &&
 399    test "$(git config branch.track2.merge)"
 400    git config branch.autosetupmerge false'
 401
 402test_expect_success 'checkout w/--track from non-branch HEAD fails' '
 403    git checkout master^0 &&
 404    test_must_fail git symbolic-ref HEAD &&
 405    test_must_fail git checkout --track -b track &&
 406    test_must_fail git rev-parse --verify track &&
 407    test_must_fail git symbolic-ref HEAD &&
 408    test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
 409'
 410
 411test_expect_success 'checkout w/--track from tag fails' '
 412    git checkout master^0 &&
 413    test_must_fail git symbolic-ref HEAD &&
 414    test_must_fail git checkout --track -b track frotz &&
 415    test_must_fail git rev-parse --verify track &&
 416    test_must_fail git symbolic-ref HEAD &&
 417    test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
 418'
 419
 420test_expect_success 'detach a symbolic link HEAD' '
 421    git checkout master &&
 422    git config --bool core.prefersymlinkrefs yes &&
 423    git checkout side &&
 424    git checkout master &&
 425    it=$(git symbolic-ref HEAD) &&
 426    test "z$it" = zrefs/heads/master &&
 427    here=$(git rev-parse --verify refs/heads/master) &&
 428    git checkout side^ &&
 429    test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
 430'
 431
 432test_expect_success \
 433    'checkout with --track fakes a sensible -b <name>' '
 434    git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
 435    git update-ref refs/remotes/origin/koala/bear renamer &&
 436
 437    git checkout --track origin/koala/bear &&
 438    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 439    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
 440
 441    git checkout master && git branch -D koala/bear &&
 442
 443    git checkout --track refs/remotes/origin/koala/bear &&
 444    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 445    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
 446
 447    git checkout master && git branch -D koala/bear &&
 448
 449    git checkout --track remotes/origin/koala/bear &&
 450    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 451    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
 452'
 453
 454test_expect_success \
 455    'checkout with --track, but without -b, fails with too short tracked name' '
 456    test_must_fail git checkout --track renamer'
 457
 458setup_conflicting_index () {
 459        rm -f .git/index &&
 460        O=$(echo original | git hash-object -w --stdin) &&
 461        A=$(echo ourside | git hash-object -w --stdin) &&
 462        B=$(echo theirside | git hash-object -w --stdin) &&
 463        (
 464                echo "100644 $A 0       fild" &&
 465                echo "100644 $O 1       file" &&
 466                echo "100644 $A 2       file" &&
 467                echo "100644 $B 3       file" &&
 468                echo "100644 $A 0       filf"
 469        ) | git update-index --index-info
 470}
 471
 472test_expect_success 'checkout an unmerged path should fail' '
 473        setup_conflicting_index &&
 474        echo "none of the above" >sample &&
 475        cat sample >fild &&
 476        cat sample >file &&
 477        cat sample >filf &&
 478        test_must_fail git checkout fild file filf &&
 479        test_cmp sample fild &&
 480        test_cmp sample filf &&
 481        test_cmp sample file
 482'
 483
 484test_expect_success 'checkout with an unmerged path can be ignored' '
 485        setup_conflicting_index &&
 486        echo "none of the above" >sample &&
 487        echo ourside >expect &&
 488        cat sample >fild &&
 489        cat sample >file &&
 490        cat sample >filf &&
 491        git checkout -f fild file filf &&
 492        test_cmp expect fild &&
 493        test_cmp expect filf &&
 494        test_cmp sample file
 495'
 496
 497test_expect_success 'checkout unmerged stage' '
 498        setup_conflicting_index &&
 499        echo "none of the above" >sample &&
 500        echo ourside >expect &&
 501        cat sample >fild &&
 502        cat sample >file &&
 503        cat sample >filf &&
 504        git checkout --ours . &&
 505        test_cmp expect fild &&
 506        test_cmp expect filf &&
 507        test_cmp expect file &&
 508        git checkout --theirs file &&
 509        test ztheirside = "z$(cat file)"
 510'
 511
 512test_expect_success 'checkout with --merge' '
 513        setup_conflicting_index &&
 514        echo "none of the above" >sample &&
 515        echo ourside >expect &&
 516        cat sample >fild &&
 517        cat sample >file &&
 518        cat sample >filf &&
 519        git checkout -m -- fild file filf &&
 520        (
 521                echo "<<<<<<< ours"
 522                echo ourside
 523                echo "======="
 524                echo theirside
 525                echo ">>>>>>> theirs"
 526        ) >merged &&
 527        test_cmp expect fild &&
 528        test_cmp expect filf &&
 529        test_cmp merged file
 530'
 531
 532test_expect_success 'checkout with --merge, in diff3 -m style' '
 533        git config merge.conflictstyle diff3 &&
 534        setup_conflicting_index &&
 535        echo "none of the above" >sample &&
 536        echo ourside >expect &&
 537        cat sample >fild &&
 538        cat sample >file &&
 539        cat sample >filf &&
 540        git checkout -m -- fild file filf &&
 541        (
 542                echo "<<<<<<< ours"
 543                echo ourside
 544                echo "||||||| base"
 545                echo original
 546                echo "======="
 547                echo theirside
 548                echo ">>>>>>> theirs"
 549        ) >merged &&
 550        test_cmp expect fild &&
 551        test_cmp expect filf &&
 552        test_cmp merged file
 553'
 554
 555test_expect_success 'checkout --conflict=merge, overriding config' '
 556        git config merge.conflictstyle diff3 &&
 557        setup_conflicting_index &&
 558        echo "none of the above" >sample &&
 559        echo ourside >expect &&
 560        cat sample >fild &&
 561        cat sample >file &&
 562        cat sample >filf &&
 563        git checkout --conflict=merge -- fild file filf &&
 564        (
 565                echo "<<<<<<< ours"
 566                echo ourside
 567                echo "======="
 568                echo theirside
 569                echo ">>>>>>> theirs"
 570        ) >merged &&
 571        test_cmp expect fild &&
 572        test_cmp expect filf &&
 573        test_cmp merged file
 574'
 575
 576test_expect_success 'checkout --conflict=diff3' '
 577        git config --unset merge.conflictstyle
 578        setup_conflicting_index &&
 579        echo "none of the above" >sample &&
 580        echo ourside >expect &&
 581        cat sample >fild &&
 582        cat sample >file &&
 583        cat sample >filf &&
 584        git checkout --conflict=diff3 -- fild file filf &&
 585        (
 586                echo "<<<<<<< ours"
 587                echo ourside
 588                echo "||||||| base"
 589                echo original
 590                echo "======="
 591                echo theirside
 592                echo ">>>>>>> theirs"
 593        ) >merged &&
 594        test_cmp expect fild &&
 595        test_cmp expect filf &&
 596        test_cmp merged file
 597'
 598
 599test_expect_success 'failing checkout -b should not break working tree' '
 600        git reset --hard master &&
 601        git symbolic-ref HEAD refs/heads/master &&
 602        test_must_fail git checkout -b renamer side^ &&
 603        test $(git symbolic-ref HEAD) = refs/heads/master &&
 604        git diff --exit-code &&
 605        git diff --cached --exit-code
 606
 607'
 608
 609test_expect_success 'switch out of non-branch' '
 610        git reset --hard master &&
 611        git checkout master^0 &&
 612        echo modified >one &&
 613        test_must_fail git checkout renamer 2>error.log &&
 614        ! grep "^Previous HEAD" error.log
 615'
 616
 617(
 618 echo "#!$SHELL_PATH"
 619 cat <<\EOF
 620O=$1 A=$2 B=$3
 621cat "$A" >.tmp
 622exec >"$A"
 623echo '<<<<<<< filfre-theirs'
 624cat "$B"
 625echo '||||||| filfre-common'
 626cat "$O"
 627echo '======='
 628cat ".tmp"
 629echo '>>>>>>> filfre-ours'
 630rm -f .tmp
 631exit 1
 632EOF
 633) >filfre.sh
 634chmod +x filfre.sh
 635
 636test_expect_success 'custom merge driver with checkout -m' '
 637        git reset --hard &&
 638
 639        git config merge.filfre.driver "./filfre.sh %O %A %B" &&
 640        git config merge.filfre.name "Feel-free merge driver" &&
 641        git config merge.filfre.recursive binary &&
 642        echo "arm merge=filfre" >.gitattributes &&
 643
 644        git checkout -b left &&
 645        echo neutral >arm &&
 646        git add arm .gitattributes &&
 647        test_tick &&
 648        git commit -m neutral &&
 649        git branch right &&
 650
 651        echo left >arm &&
 652        test_tick &&
 653        git commit -a -m left &&
 654        git checkout right &&
 655
 656        echo right >arm &&
 657        test_tick &&
 658        git commit -a -m right &&
 659
 660        test_must_fail git merge left &&
 661        (
 662                for t in filfre-common left right
 663                do
 664                        grep $t arm || exit 1
 665                done
 666                exit 0
 667        ) &&
 668
 669        mv arm expect &&
 670        git checkout -m arm &&
 671        test_cmp expect arm
 672'
 673
 674test_done