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