t / t6022-merge-rename.shon commit t3030: use test_ln_s_add to remove SYMLINKS prerequisite (bba5604)
   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 | 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'
 250
 251test_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
 257        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 commmit" &&
 263
 264        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
 269        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
 274        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
 281        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'
 288
 289printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n11\n" >expected
 290
 291test_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'
 299
 300test_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
 306        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
 310        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
 313        test_must_fail git diff --quiet &&
 314        test_must_fail git diff --cached --quiet &&
 315
 316        test -f dir/file-in-the-way &&
 317        test -f dir~HEAD &&
 318        test_cmp expected dir~HEAD
 319'
 320
 321test_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
 327        ! 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
 332        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
 335        test_must_fail git diff --quiet &&
 336        test_must_fail git diff --cached --quiet &&
 337
 338        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'
 342
 343cat >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
 360
 361test_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
 367        test 3 -eq "$(git ls-files -u | wc -l)" &&
 368        test 3 -eq "$(git ls-files -u dir | wc -l)" &&
 369
 370        test_must_fail git diff --quiet &&
 371        test_must_fail git diff --cached --quiet &&
 372
 373        test -f dir &&
 374        test_cmp expected dir
 375'
 376
 377test_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
 380        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
 385        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
 389        test_must_fail git diff --quiet &&
 390        test_must_fail git diff --cached --quiet &&
 391
 392        test -f dir/file-in-the-way &&
 393        test -f dir~HEAD &&
 394        test_cmp expected dir~HEAD
 395'
 396
 397cat >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
 414
 415test_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
 421        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
 425        test_must_fail git diff --quiet &&
 426        test_must_fail git diff --cached --quiet &&
 427
 428        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'
 432
 433test_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
 439        mkdir one &&
 440        echo stuff >one/file &&
 441        git add -A &&
 442        git commit -m "Common commmit" &&
 443
 444        git mv one/file destdir &&
 445        git commit -m "Renamed to destdir" &&
 446
 447        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'
 454
 455test_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
 461        test 1 -eq "$(git ls-files -u | wc -l)" &&
 462
 463        test_must_fail git diff --quiet &&
 464
 465        test -f destdir/foo &&
 466        test -f one &&
 467        test -f destdir~HEAD &&
 468        test "stuff" = "$(cat destdir~HEAD)"
 469'
 470
 471test_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
 477        mkdir one &&
 478        mkdir two &&
 479        echo stuff >one/file &&
 480        echo other >two/file &&
 481        git add -A &&
 482        git commit -m "Common commmit" &&
 483
 484        git rm -rf one &&
 485        git mv two/file one &&
 486        git commit -m "Rename two/file -> one" &&
 487
 488        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'
 494
 495test_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
 500        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
 504        test_must_fail git diff --quiet &&
 505
 506        test 4 -eq $(find . | grep -v .git | wc -l) &&
 507
 508        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'
 514
 515test_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
 520        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
 524        test_must_fail git diff --quiet &&
 525
 526        test 3 -eq $(find . | grep -v .git | wc -l) &&
 527
 528        test -f one &&
 529        test -f two &&
 530        test "other" = $(cat one) &&
 531        test "stuff" = $(cat two)
 532'
 533
 534test_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
 540        echo stuff >original &&
 541        git add -A &&
 542        git commit -m "Common commmit" &&
 543
 544        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
 550        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'
 557
 558test_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
 562        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
 569        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'
 575
 576test_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
 582        echo stuff >original &&
 583        mkdir one two &&
 584        touch one/file two/file &&
 585        git add -A &&
 586        git commit -m "Common commmit" &&
 587
 588        git rm -rf one &&
 589        git mv original one &&
 590        git commit -m "Rename to one" &&
 591
 592        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'
 597
 598test_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
 602        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
 608        test -f one &&
 609        test -f two &&
 610        ! test -f original
 611'
 612
 613test_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
 619        printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >original &&
 620        git add -A &&
 621        git commit -m "Common commmit" &&
 622
 623        git mv original rename &&
 624        echo 11 >>rename &&
 625        git add -u &&
 626        git commit -m "Renamed and modified" &&
 627
 628        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'
 633
 634test_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'
 642
 643test_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
 649        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 commmit" &&
 653
 654        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
 661        git checkout -b merge-branch-2 HEAD~1 &&
 662        >unrelated-change &&
 663        git add unrelated-change &&
 664        git commit -m "Only unrelated changes"
 665'
 666
 667test_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'
 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-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'
 707
 708test_expect_success 'setup avoid unnecessary update, modify/delete' '
 709        git rm -rf . &&
 710        git clean -fdqx &&
 711        rm -rf .git &&
 712        git init &&
 713
 714        >irrelevant &&
 715        >file &&
 716        git add -A &&
 717        git commit -mA &&
 718
 719        git checkout -b side
 720        git rm -f file &&
 721        git commit -m "Delete file" &&
 722
 723        git checkout master &&
 724        echo bla >file &&
 725        git add -A &&
 726        git commit -m "Modify file"
 727'
 728
 729test_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'
 737
 738test_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
 744        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >file &&
 745        git add -A &&
 746        git commit -mA &&
 747
 748        git checkout -b side
 749        cp file newfile &&
 750        git add -A &&
 751        git commit -m "Add file copy" &&
 752
 753        git checkout master &&
 754        git mv file newfile &&
 755        git commit -m "Rename file"
 756'
 757
 758test_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'
 766
 767test_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
 773        echo ORIGINAL >file &&
 774        git add file &&
 775
 776        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'
 785
 786test_expect_success 'merge rename + small change' '
 787        git merge rename_branch &&
 788
 789        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'
 793
 794test_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
 800        printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
 801        git add original_file &&
 802        git commit -mA &&
 803
 804        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
 810        git checkout master &&
 811        echo 8.5 >>original_file &&
 812        git add original_file &&
 813        git commit -mC
 814'
 815
 816cat >expected <<\EOF &&
 8171
 8182
 8193
 8204
 8215
 8226
 8237
 8248
 825<<<<<<< HEAD:renamed_file
 8269
 827=======
 8288.5
 829>>>>>>> master^0:original_file
 830EOF
 831
 832test_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'
 837
 838cat >expected <<\EOF &&
 8391
 8402
 8413
 8424
 8435
 8446
 8457
 8468
 847<<<<<<< HEAD:original_file
 8488.5
 849=======
 8509
 851>>>>>>> rename^0:renamed_file
 852EOF
 853
 854test_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'
 860
 861test_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
 867        > 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
 872        git checkout -b rename &&
 873        git mv original_file renamed_file &&
 874        git commit -mB &&
 875
 876        git checkout master &&
 877        git rm original_file &&
 878        git commit -mC
 879'
 880
 881test_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'
 886
 887test_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'
 902
 903test_done