1#!/bin/sh
   2test_description='Merge-recursive merging renames'
   4. ./test-lib.sh
   5modify () {
   7        sed -e "$1" <"$2" >"$2.x" &&
   8        mv "$2.x" "$2"
   9}
  10test_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
  30cat >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
  48git 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 &&
  57sed -e "/^g /s/.*/g : master changes a line/" <A >A+ &&
  59mv A+ A &&
  60git commit -a -m "master updates A" &&
  61git checkout yellow &&
  63rm -f M &&
  64git commit -a -m "yellow removes M" &&
  65git 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" &&
  72git 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" &&
  79git 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" &&
  86git checkout change &&
  88sed -e "/^g /s/.*/g : changed line/" <A >A+ &&
  89mv A+ A &&
  90git commit -q -a -m "changed" &&
  91git 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" &&
  97git checkout master'
  99test_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'
 115test_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'
 132test_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'
 148test_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'
 168test_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'
 176test_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'
 186test_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'
 197test_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'
 210test_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'
 224test_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'
 240test_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 | test_i18ngrep "^Skipped B" &&
 246        git reset --hard HEAD^ &&
 247        git checkout change &&
 248        GIT_MERGE_VERBOSITY=3 git merge change+rename | test_i18ngrep "^Skipped B"
 249'
 250test_expect_success 'setup for rename + d/f conflicts' '
 252        git reset --hard &&
 253        git checkout --orphan dir-in-way &&
 254        git rm -rf . &&
 255        git clean -fdqx &&
 256        mkdir sub &&
 258        mkdir dir &&
 259        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >sub/file &&
 260        echo foo >dir/file-in-the-way &&
 261        git add -A &&
 262        git commit -m "Common commit" &&
 263        echo 11 >>sub/file &&
 265        echo more >>dir/file-in-the-way &&
 266        git add -u &&
 267        git commit -m "Commit to merge, with dir in the way" &&
 268        git checkout -b dir-not-in-way &&
 270        git reset --soft HEAD^ &&
 271        git rm -rf dir &&
 272        git commit -m "Commit to merge, with dir removed" -- dir sub/file &&
 273        git checkout -b renamed-file-has-no-conflicts dir-in-way~1 &&
 275        git rm -rf dir &&
 276        git rm sub/file &&
 277        printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n" >dir &&
 278        git add dir &&
 279        git commit -m "Independent change" &&
 280        git checkout -b renamed-file-has-conflicts dir-in-way~1 &&
 282        git rm -rf dir &&
 283        git mv sub/file dir &&
 284        echo 12 >>dir &&
 285        git add dir &&
 286        git commit -m "Conflicting change"
 287'
 288printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n11\n" >expected
 290test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way' '
 292        git reset --hard &&
 293        git checkout -q renamed-file-has-no-conflicts^0 &&
 294        git merge --strategy=recursive dir-not-in-way &&
 295        git diff --quiet &&
 296        test -f dir &&
 297        test_cmp expected dir
 298'
 299test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' '
 301        git reset --hard &&
 302        rm -rf dir~* &&
 303        git checkout -q renamed-file-has-no-conflicts^0 &&
 304        test_must_fail git merge --strategy=recursive dir-in-way >output &&
 305        test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
 307        test_i18ngrep "Auto-merging dir" output &&
 308        test_i18ngrep "Adding as dir~HEAD instead" output &&
 309        test 3 -eq "$(git ls-files -u | wc -l)" &&
 311        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 312        test_must_fail git diff --quiet &&
 314        test_must_fail git diff --cached --quiet &&
 315        test -f dir/file-in-the-way &&
 317        test -f dir~HEAD &&
 318        test_cmp expected dir~HEAD
 319'
 320test_expect_success 'Same as previous, but merged other way' '
 322        git reset --hard &&
 323        rm -rf dir~* &&
 324        git checkout -q dir-in-way^0 &&
 325        test_must_fail git merge --strategy=recursive renamed-file-has-no-conflicts >output 2>errors &&
 326        ! grep "error: refusing to lose untracked file at" errors &&
 328        test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
 329        test_i18ngrep "Auto-merging dir" output &&
 330        test_i18ngrep "Adding as dir~renamed-file-has-no-conflicts instead" output &&
 331        test 3 -eq "$(git ls-files -u | wc -l)" &&
 333        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 334        test_must_fail git diff --quiet &&
 336        test_must_fail git diff --cached --quiet &&
 337        test -f dir/file-in-the-way &&
 339        test -f dir~renamed-file-has-no-conflicts &&
 340        test_cmp expected dir~renamed-file-has-no-conflicts
 341'
 342cat >expected <<\EOF &&
 3441
 3452
 3463
 3474
 3485
 3496
 3507
 3518
 3529
 35310
 354<<<<<<< HEAD:dir
 35512
 356=======
 35711
 358>>>>>>> dir-not-in-way:sub/file
 359EOF
 360test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' '
 362        git reset --hard &&
 363        rm -rf dir~* &&
 364        git checkout -q renamed-file-has-conflicts^0 &&
 365        test_must_fail git merge --strategy=recursive dir-not-in-way &&
 366        test 3 -eq "$(git ls-files -u | wc -l)" &&
 368        test 3 -eq "$(git ls-files -u dir | wc -l)" &&
 369        test_must_fail git diff --quiet &&
 371        test_must_fail git diff --cached --quiet &&
 372        test -f dir &&
 374        test_cmp expected dir
 375'
 376test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in the way' '
 378        modify s/dir-not-in-way/dir-in-way/ expected &&
 379        git reset --hard &&
 381        rm -rf dir~* &&
 382        git checkout -q renamed-file-has-conflicts^0 &&
 383        test_must_fail git merge --strategy=recursive dir-in-way &&
 384        test 5 -eq "$(git ls-files -u | wc -l)" &&
 386        test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
 387        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 388        test_must_fail git diff --quiet &&
 390        test_must_fail git diff --cached --quiet &&
 391        test -f dir/file-in-the-way &&
 393        test -f dir~HEAD &&
 394        test_cmp expected dir~HEAD
 395'
 396cat >expected <<\EOF &&
 3981
 3992
 4003
 4014
 4025
 4036
 4047
 4058
 4069
 40710
 408<<<<<<< HEAD:sub/file
 40911
 410=======
 41112
 412>>>>>>> renamed-file-has-conflicts:dir
 413EOF
 414test_expect_success 'Same as previous, but merged other way' '
 416        git reset --hard &&
 417        rm -rf dir~* &&
 418        git checkout -q dir-in-way^0 &&
 419        test_must_fail git merge --strategy=recursive renamed-file-has-conflicts &&
 420        test 5 -eq "$(git ls-files -u | wc -l)" &&
 422        test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
 423        test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 424        test_must_fail git diff --quiet &&
 426        test_must_fail git diff --cached --quiet &&
 427        test -f dir/file-in-the-way &&
 429        test -f dir~renamed-file-has-conflicts &&
 430        test_cmp expected dir~renamed-file-has-conflicts
 431'
 432test_expect_success 'setup both rename source and destination involved in D/F conflict' '
 434        git reset --hard &&
 435        git checkout --orphan rename-dest &&
 436        git rm -rf . &&
 437        git clean -fdqx &&
 438        mkdir one &&
 440        echo stuff >one/file &&
 441        git add -A &&
 442        git commit -m "Common commit" &&
 443        git mv one/file destdir &&
 445        git commit -m "Renamed to destdir" &&
 446        git checkout -b source-conflict HEAD~1 &&
 448        git rm -rf one &&
 449        mkdir destdir &&
 450        touch one destdir/foo &&
 451        git add -A &&
 452        git commit -m "Conflicts in the way"
 453'
 454test_expect_success 'both rename source and destination involved in D/F conflict' '
 456        git reset --hard &&
 457        rm -rf dir~* &&
 458        git checkout -q rename-dest^0 &&
 459        test_must_fail git merge --strategy=recursive source-conflict &&
 460        test 1 -eq "$(git ls-files -u | wc -l)" &&
 462        test_must_fail git diff --quiet &&
 464        test -f destdir/foo &&
 466        test -f one &&
 467        test -f destdir~HEAD &&
 468        test "stuff" = "$(cat destdir~HEAD)"
 469'
 470test_expect_success 'setup pair rename to parent of other (D/F conflicts)' '
 472        git reset --hard &&
 473        git checkout --orphan rename-two &&
 474        git rm -rf . &&
 475        git clean -fdqx &&
 476        mkdir one &&
 478        mkdir two &&
 479        echo stuff >one/file &&
 480        echo other >two/file &&
 481        git add -A &&
 482        git commit -m "Common commit" &&
 483        git rm -rf one &&
 485        git mv two/file one &&
 486        git commit -m "Rename two/file -> one" &&
 487        git checkout -b rename-one HEAD~1 &&
 489        git rm -rf two &&
 490        git mv one/file two &&
 491        rm -r one &&
 492        git commit -m "Rename one/file -> two"
 493'
 494test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' '
 496        git checkout -q rename-one^0 &&
 497        mkdir one &&
 498        test_must_fail git merge --strategy=recursive rename-two &&
 499        test 2 -eq "$(git ls-files -u | wc -l)" &&
 501        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 502        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 503        test_must_fail git diff --quiet &&
 505        test 4 -eq $(find . | grep -v .git | wc -l) &&
 507        test -d one &&
 509        test -f one~rename-two &&
 510        test -f two &&
 511        test "other" = $(cat one~rename-two) &&
 512        test "stuff" = $(cat two)
 513'
 514test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean start' '
 516        git reset --hard &&
 517        git clean -fdqx &&
 518        test_must_fail git merge --strategy=recursive rename-two &&
 519        test 2 -eq "$(git ls-files -u | wc -l)" &&
 521        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 522        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 523        test_must_fail git diff --quiet &&
 525        test 3 -eq $(find . | grep -v .git | wc -l) &&
 527        test -f one &&
 529        test -f two &&
 530        test "other" = $(cat one) &&
 531        test "stuff" = $(cat two)
 532'
 533test_expect_success 'setup rename of one file to two, with directories in the way' '
 535        git reset --hard &&
 536        git checkout --orphan first-rename &&
 537        git rm -rf . &&
 538        git clean -fdqx &&
 539        echo stuff >original &&
 541        git add -A &&
 542        git commit -m "Common commit" &&
 543        mkdir two &&
 545        >two/file &&
 546        git add two/file &&
 547        git mv original one &&
 548        git commit -m "Put two/file in the way, rename to one" &&
 549        git checkout -b second-rename HEAD~1 &&
 551        mkdir one &&
 552        >one/file &&
 553        git add one/file &&
 554        git mv original two &&
 555        git commit -m "Put one/file in the way, rename to two"
 556'
 557test_expect_success 'check handling of differently renamed file with D/F conflicts' '
 559        git checkout -q first-rename^0 &&
 560        test_must_fail git merge --strategy=recursive second-rename &&
 561        test 5 -eq "$(git ls-files -s | wc -l)" &&
 563        test 3 -eq "$(git ls-files -u | wc -l)" &&
 564        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 565        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 566        test 1 -eq "$(git ls-files -u original | wc -l)" &&
 567        test 2 -eq "$(git ls-files -o | wc -l)" &&
 568        test -f one/file &&
 570        test -f two/file &&
 571        test -f one~HEAD &&
 572        test -f two~second-rename &&
 573        ! test -f original
 574'
 575test_expect_success 'setup rename one file to two; directories moving out of the way' '
 577        git reset --hard &&
 578        git checkout --orphan first-rename-redo &&
 579        git rm -rf . &&
 580        git clean -fdqx &&
 581        echo stuff >original &&
 583        mkdir one two &&
 584        touch one/file two/file &&
 585        git add -A &&
 586        git commit -m "Common commit" &&
 587        git rm -rf one &&
 589        git mv original one &&
 590        git commit -m "Rename to one" &&
 591        git checkout -b second-rename-redo HEAD~1 &&
 593        git rm -rf two &&
 594        git mv original two &&
 595        git commit -m "Rename to two"
 596'
 597test_expect_success 'check handling of differently renamed file with D/F conflicts' '
 599        git checkout -q first-rename-redo^0 &&
 600        test_must_fail git merge --strategy=recursive second-rename-redo &&
 601        test 3 -eq "$(git ls-files -u | wc -l)" &&
 603        test 1 -eq "$(git ls-files -u one | wc -l)" &&
 604        test 1 -eq "$(git ls-files -u two | wc -l)" &&
 605        test 1 -eq "$(git ls-files -u original | wc -l)" &&
 606        test 0 -eq "$(git ls-files -o | wc -l)" &&
 607        test -f one &&
 609        test -f two &&
 610        ! test -f original
 611'
 612test_expect_success 'setup avoid unnecessary update, normal rename' '
 614        git reset --hard &&
 615        git checkout --orphan avoid-unnecessary-update-1 &&
 616        git rm -rf . &&
 617        git clean -fdqx &&
 618        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >original &&
 620        git add -A &&
 621        git commit -m "Common commit" &&
 622        git mv original rename &&
 624        echo 11 >>rename &&
 625        git add -u &&
 626        git commit -m "Renamed and modified" &&
 627        git checkout -b merge-branch-1 HEAD~1 &&
 629        echo "random content" >random-file &&
 630        git add -A &&
 631        git commit -m "Random, unrelated changes"
 632'
 633test_expect_success 'avoid unnecessary update, normal rename' '
 635        git checkout -q avoid-unnecessary-update-1^0 &&
 636        test-chmtime =1000000000 rename &&
 637        test-chmtime -v +0 rename >expect &&
 638        git merge merge-branch-1 &&
 639        test-chmtime -v +0 rename >actual &&
 640        test_cmp expect actual # "rename" should have stayed intact
 641'
 642test_expect_success 'setup to test avoiding unnecessary update, with D/F conflict' '
 644        git reset --hard &&
 645        git checkout --orphan avoid-unnecessary-update-2 &&
 646        git rm -rf . &&
 647        git clean -fdqx &&
 648        mkdir df &&
 650        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >df/file &&
 651        git add -A &&
 652        git commit -m "Common commit" &&
 653        git mv df/file temp &&
 655        rm -rf df &&
 656        git mv temp df &&
 657        echo 11 >>df &&
 658        git add -u &&
 659        git commit -m "Renamed and modified" &&
 660        git checkout -b merge-branch-2 HEAD~1 &&
 662        >unrelated-change &&
 663        git add unrelated-change &&
 664        git commit -m "Only unrelated changes"
 665'
 666test_expect_success 'avoid unnecessary update, with D/F conflict' '
 668        git checkout -q avoid-unnecessary-update-2^0 &&
 669        test-chmtime =1000000000 df &&
 670        test-chmtime -v +0 df >expect &&
 671        git merge merge-branch-2 &&
 672        test-chmtime -v +0 df >actual &&
 673        test_cmp expect actual # "df" should have stayed intact
 674'
 675test_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        >irrelevant &&
 683        mkdir df &&
 684        >df/file &&
 685        git add -A &&
 686        git commit -mA &&
 687        git checkout -b side &&
 689        git rm -rf df &&
 690        git commit -mB &&
 691        git checkout master &&
 693        git rm -rf df &&
 694        echo bla >df &&
 695        git add -A &&
 696        git commit -m "Add a newfile"
 697'
 698test_expect_success 'avoid unnecessary update, dir->(file,nothing)' '
 700        git checkout -q master^0 &&
 701        test-chmtime =1000000000 df &&
 702        test-chmtime -v +0 df >expect &&
 703        git merge side &&
 704        test-chmtime -v +0 df >actual &&
 705        test_cmp expect actual # "df" should have stayed intact
 706'
 707test_expect_success 'setup avoid unnecessary update, modify/delete' '
 709        git rm -rf . &&
 710        git clean -fdqx &&
 711        rm -rf .git &&
 712        git init &&
 713        >irrelevant &&
 715        >file &&
 716        git add -A &&
 717        git commit -mA &&
 718        git checkout -b side &&
 720        git rm -f file &&
 721        git commit -m "Delete file" &&
 722        git checkout master &&
 724        echo bla >file &&
 725        git add -A &&
 726        git commit -m "Modify file"
 727'
 728test_expect_success 'avoid unnecessary update, modify/delete' '
 730        git checkout -q master^0 &&
 731        test-chmtime =1000000000 file &&
 732        test-chmtime -v +0 file >expect &&
 733        test_must_fail git merge side &&
 734        test-chmtime -v +0 file >actual &&
 735        test_cmp expect actual # "file" should have stayed intact
 736'
 737test_expect_success 'setup avoid unnecessary update, rename/add-dest' '
 739        git rm -rf . &&
 740        git clean -fdqx &&
 741        rm -rf .git &&
 742        git init &&
 743        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >file &&
 745        git add -A &&
 746        git commit -mA &&
 747        git checkout -b side &&
 749        cp file newfile &&
 750        git add -A &&
 751        git commit -m "Add file copy" &&
 752        git checkout master &&
 754        git mv file newfile &&
 755        git commit -m "Rename file"
 756'
 757test_expect_success 'avoid unnecessary update, rename/add-dest' '
 759        git checkout -q master^0 &&
 760        test-chmtime =1000000000 newfile &&
 761        test-chmtime -v +0 newfile >expect &&
 762        git merge side &&
 763        test-chmtime -v +0 newfile >actual &&
 764        test_cmp expect actual # "file" should have stayed intact
 765'
 766test_expect_success 'setup merge of rename + small change' '
 768        git reset --hard &&
 769        git checkout --orphan rename-plus-small-change &&
 770        git rm -rf . &&
 771        git clean -fdqx &&
 772        echo ORIGINAL >file &&
 774        git add file &&
 775        test_tick &&
 777        git commit -m Initial &&
 778        git checkout -b rename_branch &&
 779        git mv file renamed_file &&
 780        git commit -m Rename &&
 781        git checkout rename-plus-small-change &&
 782        echo NEW-VERSION >file &&
 783        git commit -a -m Reformat
 784'
 785test_expect_success 'merge rename + small change' '
 787        git merge rename_branch &&
 788        test 1 -eq $(git ls-files -s | wc -l) &&
 790        test 0 -eq $(git ls-files -o | wc -l) &&
 791        test $(git rev-parse HEAD:renamed_file) = $(git rev-parse HEAD~1:file)
 792'
 793test_expect_success 'setup for use of extended merge markers' '
 795        git rm -rf . &&
 796        git clean -fdqx &&
 797        rm -rf .git &&
 798        git init &&
 799        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
 801        git add original_file &&
 802        git commit -mA &&
 803        git checkout -b rename &&
 805        echo 9 >>original_file &&
 806        git add original_file &&
 807        git mv original_file renamed_file &&
 808        git commit -mB &&
 809        git checkout master &&
 811        echo 8.5 >>original_file &&
 812        git add original_file &&
 813        git commit -mC
 814'
 815cat >expected <<\EOF &&
 8171
 8182
 8193
 8204
 8215
 8226
 8237
 8248
 825<<<<<<< HEAD:renamed_file
 8269
 827=======
 8288.5
 829>>>>>>> master^0:original_file
 830EOF
 831test_expect_success 'merge master into rename has correct extended markers' '
 833        git checkout rename^0 &&
 834        test_must_fail git merge -s recursive master^0 &&
 835        test_cmp expected renamed_file
 836'
 837cat >expected <<\EOF &&
 8391
 8402
 8413
 8424
 8435
 8446
 8457
 8468
 847<<<<<<< HEAD:original_file
 8488.5
 849=======
 8509
 851>>>>>>> rename^0:renamed_file
 852EOF
 853test_expect_success 'merge rename into master has correct extended markers' '
 855        git reset --hard &&
 856        git checkout master^0 &&
 857        test_must_fail git merge -s recursive rename^0 &&
 858        test_cmp expected renamed_file
 859'
 860test_expect_success 'setup spurious "refusing to lose untracked" message' '
 862        git rm -rf . &&
 863        git clean -fdqx &&
 864        rm -rf .git &&
 865        git init &&
 866        > irrelevant_file &&
 868        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
 869        git add irrelevant_file original_file &&
 870        git commit -mA &&
 871        git checkout -b rename &&
 873        git mv original_file renamed_file &&
 874        git commit -mB &&
 875        git checkout master &&
 877        git rm original_file &&
 878        git commit -mC
 879'
 880test_expect_success 'no spurious "refusing to lose untracked" message' '
 882        git checkout master^0 &&
 883        test_must_fail git merge rename^0 2>errors.txt &&
 884        ! grep "refusing to lose untracked file" errors.txt
 885'
 886test_expect_success 'do not follow renames for empty files' '
 888        git checkout -f -b empty-base &&
 889        >empty1 &&
 890        git add empty1 &&
 891        git commit -m base &&
 892        echo content >empty1 &&
 893        git add empty1 &&
 894        git commit -m fill &&
 895        git checkout -b empty-topic HEAD^ &&
 896        git mv empty1 empty2 &&
 897        git commit -m rename &&
 898        test_must_fail git merge empty-base &&
 899        >expect &&
 900        test_cmp expect empty2
 901'
 902test_done