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