t / t6022-merge-rename.shon commit fsck: complain when .gitmodules is a symlink (b7b1fca)
   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-chmtime =1000000000 rename &&
 639        test-chmtime -v +0 rename >expect &&
 640        git merge merge-branch-1 &&
 641        test-chmtime -v +0 rename >actual &&
 642        test_cmp expect actual # "rename" should have stayed intact
 643'
 644
 645test_expect_success 'setup to test avoiding unnecessary update, with D/F conflict' '
 646        git reset --hard &&
 647        git checkout --orphan avoid-unnecessary-update-2 &&
 648        git rm -rf . &&
 649        git clean -fdqx &&
 650
 651        mkdir df &&
 652        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >df/file &&
 653        git add -A &&
 654        git commit -m "Common commit" &&
 655
 656        git mv df/file temp &&
 657        rm -rf df &&
 658        git mv temp df &&
 659        echo 11 >>df &&
 660        git add -u &&
 661        git commit -m "Renamed and modified" &&
 662
 663        git checkout -b merge-branch-2 HEAD~1 &&
 664        >unrelated-change &&
 665        git add unrelated-change &&
 666        git commit -m "Only unrelated changes"
 667'
 668
 669test_expect_success 'avoid unnecessary update, with D/F conflict' '
 670        git checkout -q avoid-unnecessary-update-2^0 &&
 671        test-chmtime =1000000000 df &&
 672        test-chmtime -v +0 df >expect &&
 673        git merge merge-branch-2 &&
 674        test-chmtime -v +0 df >actual &&
 675        test_cmp expect actual # "df" should have stayed intact
 676'
 677
 678test_expect_success 'setup avoid unnecessary update, dir->(file,nothing)' '
 679        git rm -rf . &&
 680        git clean -fdqx &&
 681        rm -rf .git &&
 682        git init &&
 683
 684        >irrelevant &&
 685        mkdir df &&
 686        >df/file &&
 687        git add -A &&
 688        git commit -mA &&
 689
 690        git checkout -b side &&
 691        git rm -rf df &&
 692        git commit -mB &&
 693
 694        git checkout master &&
 695        git rm -rf df &&
 696        echo bla >df &&
 697        git add -A &&
 698        git commit -m "Add a newfile"
 699'
 700
 701test_expect_success 'avoid unnecessary update, dir->(file,nothing)' '
 702        git checkout -q master^0 &&
 703        test-chmtime =1000000000 df &&
 704        test-chmtime -v +0 df >expect &&
 705        git merge side &&
 706        test-chmtime -v +0 df >actual &&
 707        test_cmp expect actual # "df" should have stayed intact
 708'
 709
 710test_expect_success 'setup avoid unnecessary update, modify/delete' '
 711        git rm -rf . &&
 712        git clean -fdqx &&
 713        rm -rf .git &&
 714        git init &&
 715
 716        >irrelevant &&
 717        >file &&
 718        git add -A &&
 719        git commit -mA &&
 720
 721        git checkout -b side &&
 722        git rm -f file &&
 723        git commit -m "Delete file" &&
 724
 725        git checkout master &&
 726        echo bla >file &&
 727        git add -A &&
 728        git commit -m "Modify file"
 729'
 730
 731test_expect_success 'avoid unnecessary update, modify/delete' '
 732        git checkout -q master^0 &&
 733        test-chmtime =1000000000 file &&
 734        test-chmtime -v +0 file >expect &&
 735        test_must_fail git merge side &&
 736        test-chmtime -v +0 file >actual &&
 737        test_cmp expect actual # "file" should have stayed intact
 738'
 739
 740test_expect_success 'setup avoid unnecessary update, rename/add-dest' '
 741        git rm -rf . &&
 742        git clean -fdqx &&
 743        rm -rf .git &&
 744        git init &&
 745
 746        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >file &&
 747        git add -A &&
 748        git commit -mA &&
 749
 750        git checkout -b side &&
 751        cp file newfile &&
 752        git add -A &&
 753        git commit -m "Add file copy" &&
 754
 755        git checkout master &&
 756        git mv file newfile &&
 757        git commit -m "Rename file"
 758'
 759
 760test_expect_success 'avoid unnecessary update, rename/add-dest' '
 761        git checkout -q master^0 &&
 762        test-chmtime =1000000000 newfile &&
 763        test-chmtime -v +0 newfile >expect &&
 764        git merge side &&
 765        test-chmtime -v +0 newfile >actual &&
 766        test_cmp expect actual # "file" should have stayed intact
 767'
 768
 769test_expect_success 'setup merge of rename + small change' '
 770        git reset --hard &&
 771        git checkout --orphan rename-plus-small-change &&
 772        git rm -rf . &&
 773        git clean -fdqx &&
 774
 775        echo ORIGINAL >file &&
 776        git add file &&
 777
 778        test_tick &&
 779        git commit -m Initial &&
 780        git checkout -b rename_branch &&
 781        git mv file renamed_file &&
 782        git commit -m Rename &&
 783        git checkout rename-plus-small-change &&
 784        echo NEW-VERSION >file &&
 785        git commit -a -m Reformat
 786'
 787
 788test_expect_success 'merge rename + small change' '
 789        git merge rename_branch &&
 790
 791        test 1 -eq $(git ls-files -s | wc -l) &&
 792        test 0 -eq $(git ls-files -o | wc -l) &&
 793        test $(git rev-parse HEAD:renamed_file) = $(git rev-parse HEAD~1:file)
 794'
 795
 796test_expect_success 'setup for use of extended merge markers' '
 797        git rm -rf . &&
 798        git clean -fdqx &&
 799        rm -rf .git &&
 800        git init &&
 801
 802        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
 803        git add original_file &&
 804        git commit -mA &&
 805
 806        git checkout -b rename &&
 807        echo 9 >>original_file &&
 808        git add original_file &&
 809        git mv original_file renamed_file &&
 810        git commit -mB &&
 811
 812        git checkout master &&
 813        echo 8.5 >>original_file &&
 814        git add original_file &&
 815        git commit -mC
 816'
 817
 818cat >expected <<\EOF &&
 8191
 8202
 8213
 8224
 8235
 8246
 8257
 8268
 827<<<<<<< HEAD:renamed_file
 8289
 829=======
 8308.5
 831>>>>>>> master^0:original_file
 832EOF
 833
 834test_expect_success 'merge master into rename has correct extended markers' '
 835        git checkout rename^0 &&
 836        test_must_fail git merge -s recursive master^0 &&
 837        test_cmp expected renamed_file
 838'
 839
 840cat >expected <<\EOF &&
 8411
 8422
 8433
 8444
 8455
 8466
 8477
 8488
 849<<<<<<< HEAD:original_file
 8508.5
 851=======
 8529
 853>>>>>>> rename^0:renamed_file
 854EOF
 855
 856test_expect_success 'merge rename into master has correct extended markers' '
 857        git reset --hard &&
 858        git checkout master^0 &&
 859        test_must_fail git merge -s recursive rename^0 &&
 860        test_cmp expected renamed_file
 861'
 862
 863test_expect_success 'setup spurious "refusing to lose untracked" message' '
 864        git rm -rf . &&
 865        git clean -fdqx &&
 866        rm -rf .git &&
 867        git init &&
 868
 869        > irrelevant_file &&
 870        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
 871        git add irrelevant_file original_file &&
 872        git commit -mA &&
 873
 874        git checkout -b rename &&
 875        git mv original_file renamed_file &&
 876        git commit -mB &&
 877
 878        git checkout master &&
 879        git rm original_file &&
 880        git commit -mC
 881'
 882
 883test_expect_success 'no spurious "refusing to lose untracked" message' '
 884        git checkout master^0 &&
 885        test_must_fail git merge rename^0 2>errors.txt &&
 886        ! grep "refusing to lose untracked file" errors.txt
 887'
 888
 889test_expect_success 'do not follow renames for empty files' '
 890        git checkout -f -b empty-base &&
 891        >empty1 &&
 892        git add empty1 &&
 893        git commit -m base &&
 894        echo content >empty1 &&
 895        git add empty1 &&
 896        git commit -m fill &&
 897        git checkout -b empty-topic HEAD^ &&
 898        git mv empty1 empty2 &&
 899        git commit -m rename &&
 900        test_must_fail git merge empty-base &&
 901        >expect &&
 902        test_cmp expect empty2
 903'
 904
 905test_done