t / t7201-co.shon commit $GIT_COMMON_DIR: a new environment variable (c7b3a3d)
   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 'switch to another branch while carrying a deletion' '
 227
 228        git checkout -f master && git reset --hard && git clean -f &&
 229        git rm two &&
 230
 231        test_must_fail git checkout simple 2>errs &&
 232        test_i18ngrep overwritten errs &&
 233
 234        git checkout --merge simple 2>errs &&
 235        test_i18ngrep ! overwritten errs &&
 236        git ls-files -u &&
 237        test_must_fail git cat-file -t :0:two &&
 238        test "$(git cat-file -t :1:two)" = blob &&
 239        test "$(git cat-file -t :2:two)" = blob &&
 240        test_must_fail git cat-file -t :3:two
 241'
 242
 243test_expect_success 'checkout to detach HEAD (with advice declined)' '
 244
 245        git config advice.detachedHead false &&
 246        git checkout -f renamer && git clean -f &&
 247        git checkout renamer^ 2>messages &&
 248        test_i18ngrep "HEAD is now at 7329388" messages &&
 249        test_line_count = 1 messages &&
 250        H=$(git rev-parse --verify HEAD) &&
 251        M=$(git show-ref -s --verify refs/heads/master) &&
 252        test "z$H" = "z$M" &&
 253        if git symbolic-ref HEAD >/dev/null 2>&1
 254        then
 255                echo "OOPS, HEAD is still symbolic???"
 256                false
 257        else
 258                : happy
 259        fi
 260'
 261
 262test_expect_success 'checkout to detach HEAD' '
 263        git config advice.detachedHead true &&
 264        git checkout -f renamer && git clean -f &&
 265        git checkout renamer^ 2>messages &&
 266        test_i18ngrep "HEAD is now at 7329388" messages &&
 267        test_line_count -gt 1 messages &&
 268        H=$(git rev-parse --verify HEAD) &&
 269        M=$(git show-ref -s --verify refs/heads/master) &&
 270        test "z$H" = "z$M" &&
 271        if git symbolic-ref HEAD >/dev/null 2>&1
 272        then
 273                echo "OOPS, HEAD is still symbolic???"
 274                false
 275        else
 276                : happy
 277        fi
 278'
 279
 280test_expect_success 'checkout to detach HEAD with branchname^' '
 281
 282        git checkout -f master && git clean -f &&
 283        git checkout renamer^ &&
 284        H=$(git rev-parse --verify HEAD) &&
 285        M=$(git show-ref -s --verify refs/heads/master) &&
 286        test "z$H" = "z$M" &&
 287        if git symbolic-ref HEAD >/dev/null 2>&1
 288        then
 289                echo "OOPS, HEAD is still symbolic???"
 290                false
 291        else
 292                : happy
 293        fi
 294'
 295
 296test_expect_success 'checkout to detach HEAD with :/message' '
 297
 298        git checkout -f master && git clean -f &&
 299        git checkout ":/Initial" &&
 300        H=$(git rev-parse --verify HEAD) &&
 301        M=$(git show-ref -s --verify refs/heads/master) &&
 302        test "z$H" = "z$M" &&
 303        if git symbolic-ref HEAD >/dev/null 2>&1
 304        then
 305                echo "OOPS, HEAD is still symbolic???"
 306                false
 307        else
 308                : happy
 309        fi
 310'
 311
 312test_expect_success 'checkout to detach HEAD with HEAD^0' '
 313
 314        git checkout -f master && git clean -f &&
 315        git checkout HEAD^0 &&
 316        H=$(git rev-parse --verify HEAD) &&
 317        M=$(git show-ref -s --verify refs/heads/master) &&
 318        test "z$H" = "z$M" &&
 319        if git symbolic-ref HEAD >/dev/null 2>&1
 320        then
 321                echo "OOPS, HEAD is still symbolic???"
 322                false
 323        else
 324                : happy
 325        fi
 326'
 327
 328test_expect_success 'checkout with ambiguous tag/branch names' '
 329
 330        git tag both side &&
 331        git branch both master &&
 332        git reset --hard &&
 333        git checkout master &&
 334
 335        git checkout both &&
 336        H=$(git rev-parse --verify HEAD) &&
 337        M=$(git show-ref -s --verify refs/heads/master) &&
 338        test "z$H" = "z$M" &&
 339        name=$(git symbolic-ref HEAD 2>/dev/null) &&
 340        test "z$name" = zrefs/heads/both
 341
 342'
 343
 344test_expect_success 'checkout with ambiguous tag/branch names' '
 345
 346        git reset --hard &&
 347        git checkout master &&
 348
 349        git tag frotz side &&
 350        git branch frotz master &&
 351        git reset --hard &&
 352        git checkout master &&
 353
 354        git checkout tags/frotz &&
 355        H=$(git rev-parse --verify HEAD) &&
 356        S=$(git show-ref -s --verify refs/heads/side) &&
 357        test "z$H" = "z$S" &&
 358        if name=$(git symbolic-ref HEAD 2>/dev/null)
 359        then
 360                echo "Bad -- should have detached"
 361                false
 362        else
 363                : happy
 364        fi
 365
 366'
 367
 368test_expect_success 'switch branches while in subdirectory' '
 369
 370        git reset --hard &&
 371        git checkout master &&
 372
 373        mkdir subs &&
 374        (
 375                cd subs &&
 376                git checkout side
 377        ) &&
 378        ! test -f subs/one &&
 379        rm -fr subs
 380
 381'
 382
 383test_expect_success 'checkout specific path while in subdirectory' '
 384
 385        git reset --hard &&
 386        git checkout side &&
 387        mkdir subs &&
 388        >subs/bero &&
 389        git add subs/bero &&
 390        git commit -m "add subs/bero" &&
 391
 392        git checkout master &&
 393        mkdir -p subs &&
 394        (
 395                cd subs &&
 396                git checkout side -- bero
 397        ) &&
 398        test -f subs/bero
 399
 400'
 401
 402test_expect_success \
 403    'checkout w/--track sets up tracking' '
 404    git config branch.autosetupmerge false &&
 405    git checkout master &&
 406    git checkout --track -b track1 &&
 407    test "$(git config branch.track1.remote)" &&
 408    test "$(git config branch.track1.merge)"'
 409
 410test_expect_success \
 411    'checkout w/autosetupmerge=always sets up tracking' '
 412    git config branch.autosetupmerge always &&
 413    git checkout master &&
 414    git checkout -b track2 &&
 415    test "$(git config branch.track2.remote)" &&
 416    test "$(git config branch.track2.merge)"
 417    git config branch.autosetupmerge false'
 418
 419test_expect_success 'checkout w/--track from non-branch HEAD fails' '
 420    git checkout master^0 &&
 421    test_must_fail git symbolic-ref HEAD &&
 422    test_must_fail git checkout --track -b track &&
 423    test_must_fail git rev-parse --verify track &&
 424    test_must_fail git symbolic-ref HEAD &&
 425    test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
 426'
 427
 428test_expect_success 'checkout w/--track from tag fails' '
 429    git checkout master^0 &&
 430    test_must_fail git symbolic-ref HEAD &&
 431    test_must_fail git checkout --track -b track frotz &&
 432    test_must_fail git rev-parse --verify track &&
 433    test_must_fail git symbolic-ref HEAD &&
 434    test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
 435'
 436
 437test_expect_success 'detach a symbolic link HEAD' '
 438    git checkout master &&
 439    git config --bool core.prefersymlinkrefs yes &&
 440    git checkout side &&
 441    git checkout master &&
 442    it=$(git symbolic-ref HEAD) &&
 443    test "z$it" = zrefs/heads/master &&
 444    here=$(git rev-parse --verify refs/heads/master) &&
 445    git checkout side^ &&
 446    test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
 447'
 448
 449test_expect_success \
 450    'checkout with --track fakes a sensible -b <name>' '
 451    git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
 452    git update-ref refs/remotes/origin/koala/bear renamer &&
 453
 454    git checkout --track origin/koala/bear &&
 455    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 456    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
 457
 458    git checkout master && git branch -D koala/bear &&
 459
 460    git checkout --track refs/remotes/origin/koala/bear &&
 461    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 462    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
 463
 464    git checkout master && git branch -D koala/bear &&
 465
 466    git checkout --track remotes/origin/koala/bear &&
 467    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 468    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
 469'
 470
 471test_expect_success \
 472    'checkout with --track, but without -b, fails with too short tracked name' '
 473    test_must_fail git checkout --track renamer'
 474
 475setup_conflicting_index () {
 476        rm -f .git/index &&
 477        O=$(echo original | git hash-object -w --stdin) &&
 478        A=$(echo ourside | git hash-object -w --stdin) &&
 479        B=$(echo theirside | git hash-object -w --stdin) &&
 480        (
 481                echo "100644 $A 0       fild" &&
 482                echo "100644 $O 1       file" &&
 483                echo "100644 $A 2       file" &&
 484                echo "100644 $B 3       file" &&
 485                echo "100644 $A 0       filf"
 486        ) | git update-index --index-info
 487}
 488
 489test_expect_success 'checkout an unmerged path should fail' '
 490        setup_conflicting_index &&
 491        echo "none of the above" >sample &&
 492        cat sample >fild &&
 493        cat sample >file &&
 494        cat sample >filf &&
 495        test_must_fail git checkout fild file filf &&
 496        test_cmp sample fild &&
 497        test_cmp sample filf &&
 498        test_cmp sample file
 499'
 500
 501test_expect_success 'checkout with an unmerged path can be ignored' '
 502        setup_conflicting_index &&
 503        echo "none of the above" >sample &&
 504        echo ourside >expect &&
 505        cat sample >fild &&
 506        cat sample >file &&
 507        cat sample >filf &&
 508        git checkout -f fild file filf &&
 509        test_cmp expect fild &&
 510        test_cmp expect filf &&
 511        test_cmp sample file
 512'
 513
 514test_expect_success 'checkout unmerged stage' '
 515        setup_conflicting_index &&
 516        echo "none of the above" >sample &&
 517        echo ourside >expect &&
 518        cat sample >fild &&
 519        cat sample >file &&
 520        cat sample >filf &&
 521        git checkout --ours . &&
 522        test_cmp expect fild &&
 523        test_cmp expect filf &&
 524        test_cmp expect file &&
 525        git checkout --theirs file &&
 526        test ztheirside = "z$(cat file)"
 527'
 528
 529test_expect_success 'checkout with --merge' '
 530        setup_conflicting_index &&
 531        echo "none of the above" >sample &&
 532        echo ourside >expect &&
 533        cat sample >fild &&
 534        cat sample >file &&
 535        cat sample >filf &&
 536        git checkout -m -- fild file filf &&
 537        (
 538                echo "<<<<<<< ours"
 539                echo ourside
 540                echo "======="
 541                echo theirside
 542                echo ">>>>>>> theirs"
 543        ) >merged &&
 544        test_cmp expect fild &&
 545        test_cmp expect filf &&
 546        test_cmp merged file
 547'
 548
 549test_expect_success 'checkout with --merge, in diff3 -m style' '
 550        git config merge.conflictstyle diff3 &&
 551        setup_conflicting_index &&
 552        echo "none of the above" >sample &&
 553        echo ourside >expect &&
 554        cat sample >fild &&
 555        cat sample >file &&
 556        cat sample >filf &&
 557        git checkout -m -- fild file filf &&
 558        (
 559                echo "<<<<<<< ours"
 560                echo ourside
 561                echo "||||||| base"
 562                echo original
 563                echo "======="
 564                echo theirside
 565                echo ">>>>>>> theirs"
 566        ) >merged &&
 567        test_cmp expect fild &&
 568        test_cmp expect filf &&
 569        test_cmp merged file
 570'
 571
 572test_expect_success 'checkout --conflict=merge, overriding config' '
 573        git config merge.conflictstyle diff3 &&
 574        setup_conflicting_index &&
 575        echo "none of the above" >sample &&
 576        echo ourside >expect &&
 577        cat sample >fild &&
 578        cat sample >file &&
 579        cat sample >filf &&
 580        git checkout --conflict=merge -- fild file filf &&
 581        (
 582                echo "<<<<<<< ours"
 583                echo ourside
 584                echo "======="
 585                echo theirside
 586                echo ">>>>>>> theirs"
 587        ) >merged &&
 588        test_cmp expect fild &&
 589        test_cmp expect filf &&
 590        test_cmp merged file
 591'
 592
 593test_expect_success 'checkout --conflict=diff3' '
 594        git config --unset merge.conflictstyle
 595        setup_conflicting_index &&
 596        echo "none of the above" >sample &&
 597        echo ourside >expect &&
 598        cat sample >fild &&
 599        cat sample >file &&
 600        cat sample >filf &&
 601        git checkout --conflict=diff3 -- fild file filf &&
 602        (
 603                echo "<<<<<<< ours"
 604                echo ourside
 605                echo "||||||| base"
 606                echo original
 607                echo "======="
 608                echo theirside
 609                echo ">>>>>>> theirs"
 610        ) >merged &&
 611        test_cmp expect fild &&
 612        test_cmp expect filf &&
 613        test_cmp merged file
 614'
 615
 616test_expect_success 'failing checkout -b should not break working tree' '
 617        git reset --hard master &&
 618        git symbolic-ref HEAD refs/heads/master &&
 619        test_must_fail git checkout -b renamer side^ &&
 620        test $(git symbolic-ref HEAD) = refs/heads/master &&
 621        git diff --exit-code &&
 622        git diff --cached --exit-code
 623
 624'
 625
 626test_expect_success 'switch out of non-branch' '
 627        git reset --hard master &&
 628        git checkout master^0 &&
 629        echo modified >one &&
 630        test_must_fail git checkout renamer 2>error.log &&
 631        ! grep "^Previous HEAD" error.log
 632'
 633
 634(
 635 echo "#!$SHELL_PATH"
 636 cat <<\EOF
 637O=$1 A=$2 B=$3
 638cat "$A" >.tmp
 639exec >"$A"
 640echo '<<<<<<< filfre-theirs'
 641cat "$B"
 642echo '||||||| filfre-common'
 643cat "$O"
 644echo '======='
 645cat ".tmp"
 646echo '>>>>>>> filfre-ours'
 647rm -f .tmp
 648exit 1
 649EOF
 650) >filfre.sh
 651chmod +x filfre.sh
 652
 653test_expect_success 'custom merge driver with checkout -m' '
 654        git reset --hard &&
 655
 656        git config merge.filfre.driver "./filfre.sh %O %A %B" &&
 657        git config merge.filfre.name "Feel-free merge driver" &&
 658        git config merge.filfre.recursive binary &&
 659        echo "arm merge=filfre" >.gitattributes &&
 660
 661        git checkout -b left &&
 662        echo neutral >arm &&
 663        git add arm .gitattributes &&
 664        test_tick &&
 665        git commit -m neutral &&
 666        git branch right &&
 667
 668        echo left >arm &&
 669        test_tick &&
 670        git commit -a -m left &&
 671        git checkout right &&
 672
 673        echo right >arm &&
 674        test_tick &&
 675        git commit -a -m right &&
 676
 677        test_must_fail git merge left &&
 678        (
 679                for t in filfre-common left right
 680                do
 681                        grep $t arm || exit 1
 682                done
 683                exit 0
 684        ) &&
 685
 686        mv arm expect &&
 687        git checkout -m arm &&
 688        test_cmp expect arm
 689'
 690
 691test_done