t / t6022-merge-rename.shon commit Merge branch 'ag/p3400-force-checkout' (0466aeb)
   1#!/bin/sh
   2
   3test_description='Merge-recursive merging renames'
   4. ./test-lib.sh
   5
   6modify () {
   7        sed -e "$1" <"$2" >"$2.x" &&
   8        mv "$2.x" "$2"
   9}
  10
  11test_expect_success setup \
  12'
  13cat >A <<\EOF &&
  14a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
  15b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
  16c cccccccccccccccccccccccccccccccccccccccccccccccc
  17d dddddddddddddddddddddddddddddddddddddddddddddddd
  18e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
  19f ffffffffffffffffffffffffffffffffffffffffffffffff
  20g gggggggggggggggggggggggggggggggggggggggggggggggg
  21h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
  22i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
  23j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  24k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
  25l llllllllllllllllllllllllllllllllllllllllllllllll
  26m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
  27n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
  28o oooooooooooooooooooooooooooooooooooooooooooooooo
  29EOF
  30
  31cat >M <<\EOF &&
  32A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  33B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  34C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
  35D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
  36E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  37F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  38G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
  39H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
  40I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
  41J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
  42K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
  43L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
  44M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
  45N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
  46O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  47EOF
  48
  49git add A M &&
  50git commit -m "initial has A and M" &&
  51git branch white &&
  52git branch red &&
  53git branch blue &&
  54git branch yellow &&
  55git branch change &&
  56git branch change+rename &&
  57
  58sed -e "/^g /s/.*/g : master changes a line/" <A >A+ &&
  59mv A+ A &&
  60git commit -a -m "master updates A" &&
  61
  62git checkout yellow &&
  63rm -f M &&
  64git commit -a -m "yellow removes M" &&
  65
  66git checkout white &&
  67sed -e "/^g /s/.*/g : white changes a line/" <A >B &&
  68sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
  69rm -f A M &&
  70git update-index --add --remove A B M N &&
  71git commit -m "white renames A->B, M->N" &&
  72
  73git checkout red &&
  74sed -e "/^g /s/.*/g : red changes a line/" <A >B &&
  75sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
  76rm -f A M &&
  77git update-index --add --remove A B M N &&
  78git commit -m "red renames A->B, M->N" &&
  79
  80git checkout blue &&
  81sed -e "/^g /s/.*/g : blue changes a line/" <A >C &&
  82sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
  83rm -f A M &&
  84git update-index --add --remove A C M N &&
  85git commit -m "blue renames A->C, M->N" &&
  86
  87git checkout change &&
  88sed -e "/^g /s/.*/g : changed line/" <A >A+ &&
  89mv A+ A &&
  90git commit -q -a -m "changed" &&
  91
  92git checkout change+rename &&
  93sed -e "/^g /s/.*/g : changed line/" <A >B &&
  94rm A &&
  95git update-index --add B &&
  96git commit -q -a -m "changed and renamed" &&
  97
  98git checkout master'
  99
 100test_expect_success 'pull renaming branch into unrenaming one' \
 101'
 102        git show-branch &&
 103        test_expect_code 1 git pull . white &&
 104        git ls-files -s &&
 105        git ls-files -u B >b.stages &&
 106        test_line_count = 3 b.stages &&
 107        git ls-files -s N >n.stages &&
 108        test_line_count = 1 n.stages &&
 109        sed -ne "/^g/{
 110        p
 111        q
 112        }" B | grep master &&
 113        git diff --exit-code white N
 114'
 115
 116test_expect_success 'pull renaming branch into another renaming one' \
 117'
 118        rm -f B &&
 119        git reset --hard &&
 120        git checkout red &&
 121        test_expect_code 1 git pull . white &&
 122        git ls-files -u B >b.stages &&
 123        test_line_count = 3 b.stages &&
 124        git ls-files -s N >n.stages &&
 125        test_line_count = 1 n.stages &&
 126        sed -ne "/^g/{
 127        p
 128        q
 129        }" B | grep red &&
 130        git diff --exit-code white N
 131'
 132
 133test_expect_success 'pull unrenaming branch into renaming one' \
 134'
 135        git reset --hard &&
 136        git show-branch &&
 137        test_expect_code 1 git pull . master &&
 138        git ls-files -u B >b.stages &&
 139        test_line_count = 3 b.stages &&
 140        git ls-files -s N >n.stages &&
 141        test_line_count = 1 n.stages &&
 142        sed -ne "/^g/{
 143        p
 144        q
 145        }" B | grep red &&
 146        git diff --exit-code white N
 147'
 148
 149test_expect_success 'pull conflicting renames' \
 150'
 151        git reset --hard &&
 152        git show-branch &&
 153        test_expect_code 1 git pull . blue &&
 154        git ls-files -u A >a.stages &&
 155        test_line_count = 1 a.stages &&
 156        git ls-files -u B >b.stages &&
 157        test_line_count = 1 b.stages &&
 158        git ls-files -u C >c.stages &&
 159        test_line_count = 1 c.stages &&
 160        git ls-files -s N >n.stages &&
 161        test_line_count = 1 n.stages &&
 162        sed -ne "/^g/{
 163        p
 164        q
 165        }" B | grep red &&
 166        git diff --exit-code white N
 167'
 168
 169test_expect_success 'interference with untracked working tree file' '
 170        git reset --hard &&
 171        git show-branch &&
 172        echo >A this file should not matter &&
 173        test_expect_code 1 git pull . white &&
 174        test_path_is_file A
 175'
 176
 177test_expect_success 'interference with untracked working tree file' '
 178        git reset --hard &&
 179        git checkout white &&
 180        git show-branch &&
 181        rm -f A &&
 182        echo >A this file should not matter &&
 183        test_expect_code 1 git pull . red &&
 184        test_path_is_file A
 185'
 186
 187test_expect_success 'interference with untracked working tree file' '
 188        git reset --hard &&
 189        rm -f A M &&
 190        git checkout -f master &&
 191        git tag -f anchor &&
 192        git show-branch &&
 193        git pull . yellow &&
 194        test_path_is_missing M &&
 195        git reset --hard anchor
 196'
 197
 198test_expect_success 'updated working tree file should prevent the merge' '
 199        git reset --hard &&
 200        rm -f A M &&
 201        git checkout -f master &&
 202        git tag -f anchor &&
 203        git show-branch &&
 204        echo >>M one line addition &&
 205        cat M >M.saved &&
 206        test_expect_code 128 git pull . yellow &&
 207        test_cmp M M.saved &&
 208        rm -f M.saved
 209'
 210
 211test_expect_success 'updated working tree file should prevent the merge' '
 212        git reset --hard &&
 213        rm -f A M &&
 214        git checkout -f master &&
 215        git tag -f anchor &&
 216        git show-branch &&
 217        echo >>M one line addition &&
 218        cat M >M.saved &&
 219        git update-index M &&
 220        test_expect_code 128 git pull . yellow &&
 221        test_cmp M M.saved &&
 222        rm -f M.saved
 223'
 224
 225test_expect_success 'interference with untracked working tree file' '
 226        git reset --hard &&
 227        rm -f A M &&
 228        git checkout -f yellow &&
 229        git tag -f anchor &&
 230        git show-branch &&
 231        echo >M this file should not matter &&
 232        git pull . master &&
 233        test_path_is_file M &&
 234        ! {
 235                git ls-files -s |
 236                grep M
 237        } &&
 238        git reset --hard anchor
 239'
 240
 241test_expect_success 'merge of identical changes in a renamed file' '
 242        rm -f A M N &&
 243        git reset --hard &&
 244        git checkout change+rename &&
 245        GIT_MERGE_VERBOSITY=3 git merge change >out &&
 246        test_i18ngrep "^Skipped B" out &&
 247        git reset --hard HEAD^ &&
 248        git checkout change &&
 249        GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&
 250        test_i18ngrep ! "^Skipped B" out
 251'
 252
 253test_expect_success 'setup for rename + d/f conflicts' '
 254        git reset --hard &&
 255        git checkout --orphan dir-in-way &&
 256        git rm -rf . &&
 257        git clean -fdqx &&
 258
 259        mkdir sub &&
 260        mkdir dir &&
 261        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >sub/file &&
 262        echo foo >dir/file-in-the-way &&
 263        git add -A &&
 264        git commit -m "Common commit" &&
 265
 266        echo 11 >>sub/file &&
 267        echo more >>dir/file-in-the-way &&
 268        git add -u &&
 269        git commit -m "Commit to merge, with dir in the way" &&
 270
 271        git checkout -b dir-not-in-way &&
 272        git reset --soft HEAD^ &&
 273        git rm -rf dir &&
 274        git commit -m "Commit to merge, with dir removed" -- dir sub/file &&
 275
 276        git checkout -b renamed-file-has-no-conflicts dir-in-way~1 &&
 277        git rm -rf dir &&
 278        git rm sub/file &&
 279        printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n" >dir &&
 280        git add dir &&
 281        git commit -m "Independent change" &&
 282
 283        git checkout -b renamed-file-has-conflicts dir-in-way~1 &&
 284        git rm -rf dir &&
 285        git mv sub/file dir &&
 286        echo 12 >>dir &&
 287        git add dir &&
 288        git commit -m "Conflicting change"
 289'
 290
 291printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n11\n" >expected
 292
 293test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way' '
 294        git reset --hard &&
 295        git checkout -q renamed-file-has-no-conflicts^0 &&
 296        git merge --strategy=recursive dir-not-in-way &&
 297        git diff --quiet &&
 298        test -f dir &&
 299        test_cmp expected dir
 300'
 301
 302test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' '
 303        git reset --hard &&
 304        rm -rf dir~* &&
 305        git checkout -q renamed-file-has-no-conflicts^0 &&
 306        test_must_fail git merge --strategy=recursive dir-in-way >output &&
 307
 308        test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
 309        test_i18ngrep "Auto-merging dir" output &&
 310        test_i18ngrep "Adding as dir~HEAD instead" output &&
 311
 312        test 3 -eq "$(git ls-files -u | wc -l)" &&
 313        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 314
 315        test_must_fail git diff --quiet &&
 316        test_must_fail git diff --cached --quiet &&
 317
 318        test -f dir/file-in-the-way &&
 319        test -f dir~HEAD &&
 320        test_cmp expected dir~HEAD
 321'
 322
 323test_expect_success 'Same as previous, but merged other way' '
 324        git reset --hard &&
 325        rm -rf dir~* &&
 326        git checkout -q dir-in-way^0 &&
 327        test_must_fail git merge --strategy=recursive renamed-file-has-no-conflicts >output 2>errors &&
 328
 329        ! grep "error: refusing to lose untracked file at" errors &&
 330        test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
 331        test_i18ngrep "Auto-merging dir" output &&
 332        test_i18ngrep "Adding as dir~renamed-file-has-no-conflicts instead" output &&
 333
 334        test 3 -eq "$(git ls-files -u | wc -l)" &&
 335        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 336
 337        test_must_fail git diff --quiet &&
 338        test_must_fail git diff --cached --quiet &&
 339
 340        test -f dir/file-in-the-way &&
 341        test -f dir~renamed-file-has-no-conflicts &&
 342        test_cmp expected dir~renamed-file-has-no-conflicts
 343'
 344
 345cat >expected <<\EOF &&
 3461
 3472
 3483
 3494
 3505
 3516
 3527
 3538
 3549
 35510
 356<<<<<<< HEAD:dir
 35712
 358=======
 35911
 360>>>>>>> dir-not-in-way:sub/file
 361EOF
 362
 363test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' '
 364        git reset --hard &&
 365        rm -rf dir~* &&
 366        git checkout -q renamed-file-has-conflicts^0 &&
 367        test_must_fail git merge --strategy=recursive dir-not-in-way &&
 368
 369        test 3 -eq "$(git ls-files -u | wc -l)" &&
 370        test 3 -eq "$(git ls-files -u dir | wc -l)" &&
 371
 372        test_must_fail git diff --quiet &&
 373        test_must_fail git diff --cached --quiet &&
 374
 375        test -f dir &&
 376        test_cmp expected dir
 377'
 378
 379test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in the way' '
 380        modify s/dir-not-in-way/dir-in-way/ expected &&
 381
 382        git reset --hard &&
 383        rm -rf dir~* &&
 384        git checkout -q renamed-file-has-conflicts^0 &&
 385        test_must_fail git merge --strategy=recursive dir-in-way &&
 386
 387        test 5 -eq "$(git ls-files -u | wc -l)" &&
 388        test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
 389        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 390
 391        test_must_fail git diff --quiet &&
 392        test_must_fail git diff --cached --quiet &&
 393
 394        test -f dir/file-in-the-way &&
 395        test -f dir~HEAD &&
 396        test_cmp expected dir~HEAD
 397'
 398
 399cat >expected <<\EOF &&
 4001
 4012
 4023
 4034
 4045
 4056
 4067
 4078
 4089
 40910
 410<<<<<<< HEAD:sub/file
 41111
 412=======
 41312
 414>>>>>>> renamed-file-has-conflicts:dir
 415EOF
 416
 417test_expect_success 'Same as previous, but merged other way' '
 418        git reset --hard &&
 419        rm -rf dir~* &&
 420        git checkout -q dir-in-way^0 &&
 421        test_must_fail git merge --strategy=recursive renamed-file-has-conflicts &&
 422
 423        test 5 -eq "$(git ls-files -u | wc -l)" &&
 424        test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
 425        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 426
 427        test_must_fail git diff --quiet &&
 428        test_must_fail git diff --cached --quiet &&
 429
 430        test -f dir/file-in-the-way &&
 431        test -f dir~renamed-file-has-conflicts &&
 432        test_cmp expected dir~renamed-file-has-conflicts
 433'
 434
 435test_expect_success 'setup both rename source and destination involved in D/F conflict' '
 436        git reset --hard &&
 437        git checkout --orphan rename-dest &&
 438        git rm -rf . &&
 439        git clean -fdqx &&
 440
 441        mkdir one &&
 442        echo stuff >one/file &&
 443        git add -A &&
 444        git commit -m "Common commit" &&
 445
 446        git mv one/file destdir &&
 447        git commit -m "Renamed to destdir" &&
 448
 449        git checkout -b source-conflict HEAD~1 &&
 450        git rm -rf one &&
 451        mkdir destdir &&
 452        touch one destdir/foo &&
 453        git add -A &&
 454        git commit -m "Conflicts in the way"
 455'
 456
 457test_expect_success 'both rename source and destination involved in D/F conflict' '
 458        git reset --hard &&
 459        rm -rf dir~* &&
 460        git checkout -q rename-dest^0 &&
 461        test_must_fail git merge --strategy=recursive source-conflict &&
 462
 463        test 1 -eq "$(git ls-files -u | wc -l)" &&
 464
 465        test_must_fail git diff --quiet &&
 466
 467        test -f destdir/foo &&
 468        test -f one &&
 469        test -f destdir~HEAD &&
 470        test "stuff" = "$(cat destdir~HEAD)"
 471'
 472
 473test_expect_success 'setup pair rename to parent of other (D/F conflicts)' '
 474        git reset --hard &&
 475        git checkout --orphan rename-two &&
 476        git rm -rf . &&
 477        git clean -fdqx &&
 478
 479        mkdir one &&
 480        mkdir two &&
 481        echo stuff >one/file &&
 482        echo other >two/file &&
 483        git add -A &&
 484        git commit -m "Common commit" &&
 485
 486        git rm -rf one &&
 487        git mv two/file one &&
 488        git commit -m "Rename two/file -> one" &&
 489
 490        git checkout -b rename-one HEAD~1 &&
 491        git rm -rf two &&
 492        git mv one/file two &&
 493        rm -r one &&
 494        git commit -m "Rename one/file -> two"
 495'
 496
 497test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' '
 498        git checkout -q rename-one^0 &&
 499        mkdir one &&
 500        test_must_fail git merge --strategy=recursive rename-two &&
 501
 502        test 2 -eq "$(git ls-files -u | wc -l)" &&
 503        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 504        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 505
 506        test_must_fail git diff --quiet &&
 507
 508        test 4 -eq $(find . | grep -v .git | wc -l) &&
 509
 510        test -d one &&
 511        test -f one~rename-two &&
 512        test -f two &&
 513        test "other" = $(cat one~rename-two) &&
 514        test "stuff" = $(cat two)
 515'
 516
 517test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean start' '
 518        git reset --hard &&
 519        git clean -fdqx &&
 520        test_must_fail git merge --strategy=recursive rename-two &&
 521
 522        test 2 -eq "$(git ls-files -u | wc -l)" &&
 523        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 524        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 525
 526        test_must_fail git diff --quiet &&
 527
 528        test 3 -eq $(find . | grep -v .git | wc -l) &&
 529
 530        test -f one &&
 531        test -f two &&
 532        test "other" = $(cat one) &&
 533        test "stuff" = $(cat two)
 534'
 535
 536test_expect_success 'setup rename of one file to two, with directories in the way' '
 537        git reset --hard &&
 538        git checkout --orphan first-rename &&
 539        git rm -rf . &&
 540        git clean -fdqx &&
 541
 542        echo stuff >original &&
 543        git add -A &&
 544        git commit -m "Common commit" &&
 545
 546        mkdir two &&
 547        >two/file &&
 548        git add two/file &&
 549        git mv original one &&
 550        git commit -m "Put two/file in the way, rename to one" &&
 551
 552        git checkout -b second-rename HEAD~1 &&
 553        mkdir one &&
 554        >one/file &&
 555        git add one/file &&
 556        git mv original two &&
 557        git commit -m "Put one/file in the way, rename to two"
 558'
 559
 560test_expect_success 'check handling of differently renamed file with D/F conflicts' '
 561        git checkout -q first-rename^0 &&
 562        test_must_fail git merge --strategy=recursive second-rename &&
 563
 564        test 5 -eq "$(git ls-files -s | wc -l)" &&
 565        test 3 -eq "$(git ls-files -u | wc -l)" &&
 566        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 567        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 568        test 1 -eq "$(git ls-files -u original | wc -l)" &&
 569        test 2 -eq "$(git ls-files -o | wc -l)" &&
 570
 571        test -f one/file &&
 572        test -f two/file &&
 573        test -f one~HEAD &&
 574        test -f two~second-rename &&
 575        ! test -f original
 576'
 577
 578test_expect_success 'setup rename one file to two; directories moving out of the way' '
 579        git reset --hard &&
 580        git checkout --orphan first-rename-redo &&
 581        git rm -rf . &&
 582        git clean -fdqx &&
 583
 584        echo stuff >original &&
 585        mkdir one two &&
 586        touch one/file two/file &&
 587        git add -A &&
 588        git commit -m "Common commit" &&
 589
 590        git rm -rf one &&
 591        git mv original one &&
 592        git commit -m "Rename to one" &&
 593
 594        git checkout -b second-rename-redo HEAD~1 &&
 595        git rm -rf two &&
 596        git mv original two &&
 597        git commit -m "Rename to two"
 598'
 599
 600test_expect_success 'check handling of differently renamed file with D/F conflicts' '
 601        git checkout -q first-rename-redo^0 &&
 602        test_must_fail git merge --strategy=recursive second-rename-redo &&
 603
 604        test 3 -eq "$(git ls-files -u | wc -l)" &&
 605        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 606        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 607        test 1 -eq "$(git ls-files -u original | wc -l)" &&
 608        test 0 -eq "$(git ls-files -o | wc -l)" &&
 609
 610        test -f one &&
 611        test -f two &&
 612        ! test -f original
 613'
 614
 615test_expect_success 'setup avoid unnecessary update, normal rename' '
 616        git reset --hard &&
 617        git checkout --orphan avoid-unnecessary-update-1 &&
 618        git rm -rf . &&
 619        git clean -fdqx &&
 620
 621        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >original &&
 622        git add -A &&
 623        git commit -m "Common commit" &&
 624
 625        git mv original rename &&
 626        echo 11 >>rename &&
 627        git add -u &&
 628        git commit -m "Renamed and modified" &&
 629
 630        git checkout -b merge-branch-1 HEAD~1 &&
 631        echo "random content" >random-file &&
 632        git add -A &&
 633        git commit -m "Random, unrelated changes"
 634'
 635
 636test_expect_success 'avoid unnecessary update, normal rename' '
 637        git checkout -q avoid-unnecessary-update-1^0 &&
 638        test-tool chmtime --get =1000000000 rename >expect &&
 639        git merge merge-branch-1 &&
 640        test-tool chmtime --get rename >actual &&
 641        test_cmp expect actual # "rename" should have stayed intact
 642'
 643
 644test_expect_success 'setup to test avoiding unnecessary update, with D/F conflict' '
 645        git reset --hard &&
 646        git checkout --orphan avoid-unnecessary-update-2 &&
 647        git rm -rf . &&
 648        git clean -fdqx &&
 649
 650        mkdir df &&
 651        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >df/file &&
 652        git add -A &&
 653        git commit -m "Common commit" &&
 654
 655        git mv df/file temp &&
 656        rm -rf df &&
 657        git mv temp df &&
 658        echo 11 >>df &&
 659        git add -u &&
 660        git commit -m "Renamed and modified" &&
 661
 662        git checkout -b merge-branch-2 HEAD~1 &&
 663        >unrelated-change &&
 664        git add unrelated-change &&
 665        git commit -m "Only unrelated changes"
 666'
 667
 668test_expect_success 'avoid unnecessary update, with D/F conflict' '
 669        git checkout -q avoid-unnecessary-update-2^0 &&
 670        test-tool chmtime --get =1000000000 df >expect &&
 671        git merge merge-branch-2 &&
 672        test-tool chmtime --get df >actual &&
 673        test_cmp expect actual # "df" should have stayed intact
 674'
 675
 676test_expect_success 'setup avoid unnecessary update, dir->(file,nothing)' '
 677        git rm -rf . &&
 678        git clean -fdqx &&
 679        rm -rf .git &&
 680        git init &&
 681
 682        >irrelevant &&
 683        mkdir df &&
 684        >df/file &&
 685        git add -A &&
 686        git commit -mA &&
 687
 688        git checkout -b side &&
 689        git rm -rf df &&
 690        git commit -mB &&
 691
 692        git checkout master &&
 693        git rm -rf df &&
 694        echo bla >df &&
 695        git add -A &&
 696        git commit -m "Add a newfile"
 697'
 698
 699test_expect_success 'avoid unnecessary update, dir->(file,nothing)' '
 700        git checkout -q master^0 &&
 701        test-tool chmtime --get =1000000000 df >expect &&
 702        git merge side &&
 703        test-tool chmtime --get df >actual &&
 704        test_cmp expect actual # "df" should have stayed intact
 705'
 706
 707test_expect_success 'setup avoid unnecessary update, modify/delete' '
 708        git rm -rf . &&
 709        git clean -fdqx &&
 710        rm -rf .git &&
 711        git init &&
 712
 713        >irrelevant &&
 714        >file &&
 715        git add -A &&
 716        git commit -mA &&
 717
 718        git checkout -b side &&
 719        git rm -f file &&
 720        git commit -m "Delete file" &&
 721
 722        git checkout master &&
 723        echo bla >file &&
 724        git add -A &&
 725        git commit -m "Modify file"
 726'
 727
 728test_expect_success 'avoid unnecessary update, modify/delete' '
 729        git checkout -q master^0 &&
 730        test-tool chmtime --get =1000000000 file >expect &&
 731        test_must_fail git merge side &&
 732        test-tool chmtime --get file >actual &&
 733        test_cmp expect actual # "file" should have stayed intact
 734'
 735
 736test_expect_success 'setup avoid unnecessary update, rename/add-dest' '
 737        git rm -rf . &&
 738        git clean -fdqx &&
 739        rm -rf .git &&
 740        git init &&
 741
 742        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >file &&
 743        git add -A &&
 744        git commit -mA &&
 745
 746        git checkout -b side &&
 747        cp file newfile &&
 748        git add -A &&
 749        git commit -m "Add file copy" &&
 750
 751        git checkout master &&
 752        git mv file newfile &&
 753        git commit -m "Rename file"
 754'
 755
 756test_expect_success 'avoid unnecessary update, rename/add-dest' '
 757        git checkout -q master^0 &&
 758        test-tool chmtime --get =1000000000 newfile >expect &&
 759        git merge side &&
 760        test-tool chmtime --get newfile >actual &&
 761        test_cmp expect actual # "file" should have stayed intact
 762'
 763
 764test_expect_success 'setup merge of rename + small change' '
 765        git reset --hard &&
 766        git checkout --orphan rename-plus-small-change &&
 767        git rm -rf . &&
 768        git clean -fdqx &&
 769
 770        echo ORIGINAL >file &&
 771        git add file &&
 772
 773        test_tick &&
 774        git commit -m Initial &&
 775        git checkout -b rename_branch &&
 776        git mv file renamed_file &&
 777        git commit -m Rename &&
 778        git checkout rename-plus-small-change &&
 779        echo NEW-VERSION >file &&
 780        git commit -a -m Reformat
 781'
 782
 783test_expect_success 'merge rename + small change' '
 784        git merge rename_branch &&
 785
 786        test 1 -eq $(git ls-files -s | wc -l) &&
 787        test 0 -eq $(git ls-files -o | wc -l) &&
 788        test $(git rev-parse HEAD:renamed_file) = $(git rev-parse HEAD~1:file)
 789'
 790
 791test_expect_success 'setup for use of extended merge markers' '
 792        git rm -rf . &&
 793        git clean -fdqx &&
 794        rm -rf .git &&
 795        git init &&
 796
 797        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
 798        git add original_file &&
 799        git commit -mA &&
 800
 801        git checkout -b rename &&
 802        echo 9 >>original_file &&
 803        git add original_file &&
 804        git mv original_file renamed_file &&
 805        git commit -mB &&
 806
 807        git checkout master &&
 808        echo 8.5 >>original_file &&
 809        git add original_file &&
 810        git commit -mC
 811'
 812
 813cat >expected <<\EOF &&
 8141
 8152
 8163
 8174
 8185
 8196
 8207
 8218
 822<<<<<<< HEAD:renamed_file
 8239
 824=======
 8258.5
 826>>>>>>> master^0:original_file
 827EOF
 828
 829test_expect_success 'merge master into rename has correct extended markers' '
 830        git checkout rename^0 &&
 831        test_must_fail git merge -s recursive master^0 &&
 832        test_cmp expected renamed_file
 833'
 834
 835cat >expected <<\EOF &&
 8361
 8372
 8383
 8394
 8405
 8416
 8427
 8438
 844<<<<<<< HEAD:original_file
 8458.5
 846=======
 8479
 848>>>>>>> rename^0:renamed_file
 849EOF
 850
 851test_expect_success 'merge rename into master has correct extended markers' '
 852        git reset --hard &&
 853        git checkout master^0 &&
 854        test_must_fail git merge -s recursive rename^0 &&
 855        test_cmp expected renamed_file
 856'
 857
 858test_expect_success 'setup spurious "refusing to lose untracked" message' '
 859        git rm -rf . &&
 860        git clean -fdqx &&
 861        rm -rf .git &&
 862        git init &&
 863
 864        > irrelevant_file &&
 865        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
 866        git add irrelevant_file original_file &&
 867        git commit -mA &&
 868
 869        git checkout -b rename &&
 870        git mv original_file renamed_file &&
 871        git commit -mB &&
 872
 873        git checkout master &&
 874        git rm original_file &&
 875        git commit -mC
 876'
 877
 878test_expect_success 'no spurious "refusing to lose untracked" message' '
 879        git checkout master^0 &&
 880        test_must_fail git merge rename^0 2>errors.txt &&
 881        ! grep "refusing to lose untracked file" errors.txt
 882'
 883
 884test_expect_success 'do not follow renames for empty files' '
 885        git checkout -f -b empty-base &&
 886        >empty1 &&
 887        git add empty1 &&
 888        git commit -m base &&
 889        echo content >empty1 &&
 890        git add empty1 &&
 891        git commit -m fill &&
 892        git checkout -b empty-topic HEAD^ &&
 893        git mv empty1 empty2 &&
 894        git commit -m rename &&
 895        test_must_fail git merge empty-base &&
 896        test_must_be_empty empty2
 897'
 898
 899test_done