t / t7201-co.shon commit Merge branch 'maint' (a66cee2)
   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        grep "HEAD is now at 7329388" messages &&
 232        test 1 -eq $(wc -l <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        grep "HEAD is now at 7329388" messages &&
 250        test 1 -lt $(wc -l <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 'detach a symbolic link HEAD' '
 412    git checkout master &&
 413    git config --bool core.prefersymlinkrefs yes &&
 414    git checkout side &&
 415    git checkout master &&
 416    it=$(git symbolic-ref HEAD) &&
 417    test "z$it" = zrefs/heads/master &&
 418    here=$(git rev-parse --verify refs/heads/master) &&
 419    git checkout side^ &&
 420    test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
 421'
 422
 423test_expect_success \
 424    'checkout with --track fakes a sensible -b <name>' '
 425    git update-ref refs/remotes/origin/koala/bear renamer &&
 426    git update-ref refs/new/koala/bear renamer &&
 427
 428    git checkout --track origin/koala/bear &&
 429    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 430    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
 431
 432    git checkout master && git branch -D koala/bear &&
 433
 434    git checkout --track refs/remotes/origin/koala/bear &&
 435    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 436    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
 437
 438    git checkout master && git branch -D koala/bear &&
 439
 440    git checkout --track remotes/origin/koala/bear &&
 441    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 442    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
 443
 444    git checkout master && git branch -D koala/bear &&
 445
 446    git checkout --track refs/new/koala/bear &&
 447    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
 448    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
 449'
 450
 451test_expect_success \
 452    'checkout with --track, but without -b, fails with too short tracked name' '
 453    test_must_fail git checkout --track renamer'
 454
 455setup_conflicting_index () {
 456        rm -f .git/index &&
 457        O=$(echo original | git hash-object -w --stdin) &&
 458        A=$(echo ourside | git hash-object -w --stdin) &&
 459        B=$(echo theirside | git hash-object -w --stdin) &&
 460        (
 461                echo "100644 $A 0       fild" &&
 462                echo "100644 $O 1       file" &&
 463                echo "100644 $A 2       file" &&
 464                echo "100644 $B 3       file" &&
 465                echo "100644 $A 0       filf"
 466        ) | git update-index --index-info
 467}
 468
 469test_expect_success 'checkout an unmerged path should fail' '
 470        setup_conflicting_index &&
 471        echo "none of the above" >sample &&
 472        cat sample >fild &&
 473        cat sample >file &&
 474        cat sample >filf &&
 475        test_must_fail git checkout fild file filf &&
 476        test_cmp sample fild &&
 477        test_cmp sample filf &&
 478        test_cmp sample file
 479'
 480
 481test_expect_success 'checkout with an unmerged path can be ignored' '
 482        setup_conflicting_index &&
 483        echo "none of the above" >sample &&
 484        echo ourside >expect &&
 485        cat sample >fild &&
 486        cat sample >file &&
 487        cat sample >filf &&
 488        git checkout -f fild file filf &&
 489        test_cmp expect fild &&
 490        test_cmp expect filf &&
 491        test_cmp sample file
 492'
 493
 494test_expect_success 'checkout unmerged stage' '
 495        setup_conflicting_index &&
 496        echo "none of the above" >sample &&
 497        echo ourside >expect &&
 498        cat sample >fild &&
 499        cat sample >file &&
 500        cat sample >filf &&
 501        git checkout --ours . &&
 502        test_cmp expect fild &&
 503        test_cmp expect filf &&
 504        test_cmp expect file &&
 505        git checkout --theirs file &&
 506        test ztheirside = "z$(cat file)"
 507'
 508
 509test_expect_success 'checkout with --merge' '
 510        setup_conflicting_index &&
 511        echo "none of the above" >sample &&
 512        echo ourside >expect &&
 513        cat sample >fild &&
 514        cat sample >file &&
 515        cat sample >filf &&
 516        git checkout -m -- fild file filf &&
 517        (
 518                echo "<<<<<<< ours"
 519                echo ourside
 520                echo "======="
 521                echo theirside
 522                echo ">>>>>>> theirs"
 523        ) >merged &&
 524        test_cmp expect fild &&
 525        test_cmp expect filf &&
 526        test_cmp merged file
 527'
 528
 529test_expect_success 'checkout with --merge, in diff3 -m style' '
 530        git config merge.conflictstyle diff3 &&
 531        setup_conflicting_index &&
 532        echo "none of the above" >sample &&
 533        echo ourside >expect &&
 534        cat sample >fild &&
 535        cat sample >file &&
 536        cat sample >filf &&
 537        git checkout -m -- fild file filf &&
 538        (
 539                echo "<<<<<<< ours"
 540                echo ourside
 541                echo "||||||| base"
 542                echo original
 543                echo "======="
 544                echo theirside
 545                echo ">>>>>>> theirs"
 546        ) >merged &&
 547        test_cmp expect fild &&
 548        test_cmp expect filf &&
 549        test_cmp merged file
 550'
 551
 552test_expect_success 'checkout --conflict=merge, overriding config' '
 553        git config merge.conflictstyle diff3 &&
 554        setup_conflicting_index &&
 555        echo "none of the above" >sample &&
 556        echo ourside >expect &&
 557        cat sample >fild &&
 558        cat sample >file &&
 559        cat sample >filf &&
 560        git checkout --conflict=merge -- fild file filf &&
 561        (
 562                echo "<<<<<<< ours"
 563                echo ourside
 564                echo "======="
 565                echo theirside
 566                echo ">>>>>>> theirs"
 567        ) >merged &&
 568        test_cmp expect fild &&
 569        test_cmp expect filf &&
 570        test_cmp merged file
 571'
 572
 573test_expect_success 'checkout --conflict=diff3' '
 574        git config --unset merge.conflictstyle
 575        setup_conflicting_index &&
 576        echo "none of the above" >sample &&
 577        echo ourside >expect &&
 578        cat sample >fild &&
 579        cat sample >file &&
 580        cat sample >filf &&
 581        git checkout --conflict=diff3 -- fild file filf &&
 582        (
 583                echo "<<<<<<< ours"
 584                echo ourside
 585                echo "||||||| base"
 586                echo original
 587                echo "======="
 588                echo theirside
 589                echo ">>>>>>> theirs"
 590        ) >merged &&
 591        test_cmp expect fild &&
 592        test_cmp expect filf &&
 593        test_cmp merged file
 594'
 595
 596test_expect_success 'failing checkout -b should not break working tree' '
 597        git reset --hard master &&
 598        git symbolic-ref HEAD refs/heads/master &&
 599        test_must_fail git checkout -b renamer side^ &&
 600        test $(git symbolic-ref HEAD) = refs/heads/master &&
 601        git diff --exit-code &&
 602        git diff --cached --exit-code
 603
 604'
 605
 606test_expect_success 'switch out of non-branch' '
 607        git reset --hard master &&
 608        git checkout master^0 &&
 609        echo modified >one &&
 610        test_must_fail git checkout renamer 2>error.log &&
 611        ! grep "^Previous HEAD" error.log
 612'
 613
 614(
 615 echo "#!$SHELL_PATH"
 616 cat <<\EOF
 617O=$1 A=$2 B=$3
 618cat "$A" >.tmp
 619exec >"$A"
 620echo '<<<<<<< filfre-theirs'
 621cat "$B"
 622echo '||||||| filfre-common'
 623cat "$O"
 624echo '======='
 625cat ".tmp"
 626echo '>>>>>>> filfre-ours'
 627rm -f .tmp
 628exit 1
 629EOF
 630) >filfre.sh
 631chmod +x filfre.sh
 632
 633test_expect_success 'custom merge driver with checkout -m' '
 634        git reset --hard &&
 635
 636        git config merge.filfre.driver "./filfre.sh %O %A %B" &&
 637        git config merge.filfre.name "Feel-free merge driver" &&
 638        git config merge.filfre.recursive binary &&
 639        echo "arm merge=filfre" >.gitattributes &&
 640
 641        git checkout -b left &&
 642        echo neutral >arm &&
 643        git add arm .gitattributes &&
 644        test_tick &&
 645        git commit -m neutral &&
 646        git branch right &&
 647
 648        echo left >arm &&
 649        test_tick &&
 650        git commit -a -m left &&
 651        git checkout right &&
 652
 653        echo right >arm &&
 654        test_tick &&
 655        git commit -a -m right &&
 656
 657        test_must_fail git merge left &&
 658        (
 659                for t in filfre-common left right
 660                do
 661                        grep $t arm || exit 1
 662                done
 663                exit 0
 664        ) &&
 665
 666        mv arm expect &&
 667        git checkout -m arm &&
 668        test_cmp expect arm
 669'
 670
 671test_done