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