t / t6042-merge-rename-corner-cases.shon commit Merge branch 'ml/userdiff-rust' (a41dad4)
   1#!/bin/sh
   2
   3test_description="recursive merge corner cases w/ renames but not criss-crosses"
   4# t6036 has corner cases that involve both criss-cross merges and renames
   5
   6. ./test-lib.sh
   7
   8test_expect_success 'setup rename/delete + untracked file' '
   9        test_create_repo rename-delete-untracked &&
  10        (
  11                cd rename-delete-untracked &&
  12
  13                echo "A pretty inscription" >ring &&
  14                git add ring &&
  15                test_tick &&
  16                git commit -m beginning &&
  17
  18                git branch people &&
  19                git checkout -b rename-the-ring &&
  20                git mv ring one-ring-to-rule-them-all &&
  21                test_tick &&
  22                git commit -m fullname &&
  23
  24                git checkout people &&
  25                git rm ring &&
  26                echo gollum >owner &&
  27                git add owner &&
  28                test_tick &&
  29                git commit -m track-people-instead-of-objects &&
  30                echo "Myyy PRECIOUSSS" >ring
  31        )
  32'
  33
  34test_expect_success "Does git preserve Gollum's precious artifact?" '
  35        (
  36                cd rename-delete-untracked &&
  37
  38                test_must_fail git merge -s recursive rename-the-ring &&
  39
  40                # Make sure git did not delete an untracked file
  41                test_path_is_file ring
  42        )
  43'
  44
  45# Testcase setup for rename/modify/add-source:
  46#   Commit A: new file: a
  47#   Commit B: modify a slightly
  48#   Commit C: rename a->b, add completely different a
  49#
  50# We should be able to merge B & C cleanly
  51
  52test_expect_success 'setup rename/modify/add-source conflict' '
  53        test_create_repo rename-modify-add-source &&
  54        (
  55                cd rename-modify-add-source &&
  56
  57                printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
  58                git add a &&
  59                git commit -m A &&
  60                git tag A &&
  61
  62                git checkout -b B A &&
  63                echo 8 >>a &&
  64                git add a &&
  65                git commit -m B &&
  66
  67                git checkout -b C A &&
  68                git mv a b &&
  69                echo something completely different >a &&
  70                git add a &&
  71                git commit -m C
  72        )
  73'
  74
  75test_expect_failure 'rename/modify/add-source conflict resolvable' '
  76        (
  77                cd rename-modify-add-source &&
  78
  79                git checkout B^0 &&
  80
  81                git merge -s recursive C^0 &&
  82
  83                git rev-parse >expect \
  84                        B:a   C:a     &&
  85                git rev-parse >actual \
  86                        b     c       &&
  87                test_cmp expect actual
  88        )
  89'
  90
  91test_expect_success 'setup resolvable conflict missed if rename missed' '
  92        test_create_repo break-detection-1 &&
  93        (
  94                cd break-detection-1 &&
  95
  96                printf "1\n2\n3\n4\n5\n" >a &&
  97                echo foo >b &&
  98                git add a b &&
  99                git commit -m A &&
 100                git tag A &&
 101
 102                git checkout -b B A &&
 103                git mv a c &&
 104                echo "Completely different content" >a &&
 105                git add a &&
 106                git commit -m B &&
 107
 108                git checkout -b C A &&
 109                echo 6 >>a &&
 110                git add a &&
 111                git commit -m C
 112        )
 113'
 114
 115test_expect_failure 'conflict caused if rename not detected' '
 116        (
 117                cd break-detection-1 &&
 118
 119                git checkout -q C^0 &&
 120                git merge -s recursive B^0 &&
 121
 122                git ls-files -s >out &&
 123                test_line_count = 3 out &&
 124                git ls-files -u >out &&
 125                test_line_count = 0 out &&
 126                git ls-files -o >out &&
 127                test_line_count = 1 out &&
 128
 129                test_line_count = 6 c &&
 130                git rev-parse >expect \
 131                        B:a   A:b     &&
 132                git rev-parse >actual \
 133                        :0:a  :0:b    &&
 134                test_cmp expect actual
 135        )
 136'
 137
 138test_expect_success 'setup conflict resolved wrong if rename missed' '
 139        test_create_repo break-detection-2 &&
 140        (
 141                cd break-detection-2 &&
 142
 143                printf "1\n2\n3\n4\n5\n" >a &&
 144                echo foo >b &&
 145                git add a b &&
 146                git commit -m A &&
 147                git tag A &&
 148
 149                git checkout -b D A &&
 150                echo 7 >>a &&
 151                git add a &&
 152                git mv a c &&
 153                echo "Completely different content" >a &&
 154                git add a &&
 155                git commit -m D &&
 156
 157                git checkout -b E A &&
 158                git rm a &&
 159                echo "Completely different content" >>a &&
 160                git add a &&
 161                git commit -m E
 162        )
 163'
 164
 165test_expect_failure 'missed conflict if rename not detected' '
 166        (
 167                cd break-detection-2 &&
 168
 169                git checkout -q E^0 &&
 170                test_must_fail git merge -s recursive D^0
 171        )
 172'
 173
 174# Tests for undetected rename/add-source causing a file to erroneously be
 175# deleted (and for mishandled rename/rename(1to1) causing the same issue).
 176#
 177# This test uses a rename/rename(1to1)+add-source conflict (1to1 means the
 178# same file is renamed on both sides to the same thing; it should trigger
 179# the 1to2 logic, which it would do if the add-source didn't cause issues
 180# for git's rename detection):
 181#   Commit A: new file: a
 182#   Commit B: rename a->b
 183#   Commit C: rename a->b, add unrelated a
 184
 185test_expect_success 'setup undetected rename/add-source causes data loss' '
 186        test_create_repo break-detection-3 &&
 187        (
 188                cd break-detection-3 &&
 189
 190                printf "1\n2\n3\n4\n5\n" >a &&
 191                git add a &&
 192                git commit -m A &&
 193                git tag A &&
 194
 195                git checkout -b B A &&
 196                git mv a b &&
 197                git commit -m B &&
 198
 199                git checkout -b C A &&
 200                git mv a b &&
 201                echo foobar >a &&
 202                git add a &&
 203                git commit -m C
 204        )
 205'
 206
 207test_expect_failure 'detect rename/add-source and preserve all data' '
 208        (
 209                cd break-detection-3 &&
 210
 211                git checkout B^0 &&
 212
 213                git merge -s recursive C^0 &&
 214
 215                git ls-files -s >out &&
 216                test_line_count = 2 out &&
 217                git ls-files -u >out &&
 218                test_line_count = 2 out &&
 219                git ls-files -o >out &&
 220                test_line_count = 1 out &&
 221
 222                test_path_is_file a &&
 223                test_path_is_file b &&
 224
 225                git rev-parse >expect \
 226                        A:a   C:a     &&
 227                git rev-parse >actual \
 228                        :0:b  :0:a    &&
 229                test_cmp expect actual
 230        )
 231'
 232
 233test_expect_failure 'detect rename/add-source and preserve all data, merge other way' '
 234        (
 235                cd break-detection-3 &&
 236
 237                git checkout C^0 &&
 238
 239                git merge -s recursive B^0 &&
 240
 241                git ls-files -s >out &&
 242                test_line_count = 2 out &&
 243                git ls-files -u >out &&
 244                test_line_count = 2 out &&
 245                git ls-files -o >out &&
 246                test_line_count = 1 out &&
 247
 248                test_path_is_file a &&
 249                test_path_is_file b &&
 250
 251                git rev-parse >expect \
 252                        A:a   C:a     &&
 253                git rev-parse >actual \
 254                        :0:b  :0:a    &&
 255                test_cmp expect actual
 256        )
 257'
 258
 259test_expect_success 'setup content merge + rename/directory conflict' '
 260        test_create_repo rename-directory-1 &&
 261        (
 262                cd rename-directory-1 &&
 263
 264                printf "1\n2\n3\n4\n5\n6\n" >file &&
 265                git add file &&
 266                test_tick &&
 267                git commit -m base &&
 268                git tag base &&
 269
 270                git checkout -b right &&
 271                echo 7 >>file &&
 272                mkdir newfile &&
 273                echo junk >newfile/realfile &&
 274                git add file newfile/realfile &&
 275                test_tick &&
 276                git commit -m right &&
 277
 278                git checkout -b left-conflict base &&
 279                echo 8 >>file &&
 280                git add file &&
 281                git mv file newfile &&
 282                test_tick &&
 283                git commit -m left &&
 284
 285                git checkout -b left-clean base &&
 286                echo 0 >newfile &&
 287                cat file >>newfile &&
 288                git add newfile &&
 289                git rm file &&
 290                test_tick &&
 291                git commit -m left
 292        )
 293'
 294
 295test_expect_success 'rename/directory conflict + clean content merge' '
 296        (
 297                cd rename-directory-1 &&
 298
 299                git checkout left-clean^0 &&
 300
 301                test_must_fail git merge -s recursive right^0 &&
 302
 303                git ls-files -s >out &&
 304                test_line_count = 2 out &&
 305                git ls-files -u >out &&
 306                test_line_count = 1 out &&
 307                git ls-files -o >out &&
 308                test_line_count = 2 out &&
 309
 310                echo 0 >expect &&
 311                git cat-file -p base:file >>expect &&
 312                echo 7 >>expect &&
 313                test_cmp expect newfile~HEAD &&
 314
 315                test $(git rev-parse :2:newfile) = $(git hash-object expect) &&
 316
 317                test_path_is_file newfile/realfile &&
 318                test_path_is_file newfile~HEAD
 319        )
 320'
 321
 322test_expect_success 'rename/directory conflict + content merge conflict' '
 323        (
 324                cd rename-directory-1 &&
 325
 326                git reset --hard &&
 327                git clean -fdqx &&
 328
 329                git checkout left-conflict^0 &&
 330
 331                test_must_fail git merge -s recursive right^0 &&
 332
 333                git ls-files -s >out &&
 334                test_line_count = 4 out &&
 335                git ls-files -u >out &&
 336                test_line_count = 3 out &&
 337                git ls-files -o >out &&
 338                test_line_count = 2 out &&
 339
 340                git cat-file -p left-conflict:newfile >left &&
 341                git cat-file -p base:file    >base &&
 342                git cat-file -p right:file   >right &&
 343                test_must_fail git merge-file \
 344                        -L "HEAD:newfile" \
 345                        -L "" \
 346                        -L "right^0:file" \
 347                        left base right &&
 348                test_cmp left newfile~HEAD &&
 349
 350                git rev-parse >expect                                 \
 351                        base:file   left-conflict:newfile  right:file &&
 352                git rev-parse >actual                                 \
 353                        :1:newfile  :2:newfile             :3:newfile &&
 354                test_cmp expect actual &&
 355
 356                test_path_is_file newfile/realfile &&
 357                test_path_is_file newfile~HEAD
 358        )
 359'
 360
 361test_expect_success 'setup content merge + rename/directory conflict w/ disappearing dir' '
 362        test_create_repo rename-directory-2 &&
 363        (
 364                cd rename-directory-2 &&
 365
 366                mkdir sub &&
 367                printf "1\n2\n3\n4\n5\n6\n" >sub/file &&
 368                git add sub/file &&
 369                test_tick &&
 370                git commit -m base &&
 371                git tag base &&
 372
 373                git checkout -b right &&
 374                echo 7 >>sub/file &&
 375                git add sub/file &&
 376                test_tick &&
 377                git commit -m right &&
 378
 379                git checkout -b left base &&
 380                echo 0 >newfile &&
 381                cat sub/file >>newfile &&
 382                git rm sub/file &&
 383                mv newfile sub &&
 384                git add sub &&
 385                test_tick &&
 386                git commit -m left
 387        )
 388'
 389
 390test_expect_success 'disappearing dir in rename/directory conflict handled' '
 391        (
 392                cd rename-directory-2 &&
 393
 394                git checkout left^0 &&
 395
 396                git merge -s recursive right^0 &&
 397
 398                git ls-files -s >out &&
 399                test_line_count = 1 out &&
 400                git ls-files -u >out &&
 401                test_line_count = 0 out &&
 402                git ls-files -o >out &&
 403                test_line_count = 1 out &&
 404
 405                echo 0 >expect &&
 406                git cat-file -p base:sub/file >>expect &&
 407                echo 7 >>expect &&
 408                test_cmp expect sub &&
 409
 410                test_path_is_file sub
 411        )
 412'
 413
 414# Test for basic rename/add-dest conflict, with rename needing content merge:
 415#   Commit O: a
 416#   Commit A: rename a->b, modifying b too
 417#   Commit B: modify a, add different b
 418
 419test_expect_success 'setup rename-with-content-merge vs. add' '
 420        test_create_repo rename-with-content-merge-and-add &&
 421        (
 422                cd rename-with-content-merge-and-add &&
 423
 424                test_seq 1 5 >a &&
 425                git add a &&
 426                git commit -m O &&
 427                git tag O &&
 428
 429                git checkout -b A O &&
 430                git mv a b &&
 431                test_seq 0 5 >b &&
 432                git add b &&
 433                git commit -m A &&
 434
 435                git checkout -b B O &&
 436                echo 6 >>a &&
 437                echo hello world >b &&
 438                git add a b &&
 439                git commit -m B
 440        )
 441'
 442
 443test_expect_success 'handle rename-with-content-merge vs. add' '
 444        (
 445                cd rename-with-content-merge-and-add &&
 446
 447                git checkout A^0 &&
 448
 449                test_must_fail git merge -s recursive B^0 >out &&
 450                test_i18ngrep "CONFLICT (rename/add)" out &&
 451
 452                git ls-files -s >out &&
 453                test_line_count = 2 out &&
 454                git ls-files -u >out &&
 455                test_line_count = 2 out &&
 456                # Also, make sure both unmerged entries are for "b"
 457                git ls-files -u b >out &&
 458                test_line_count = 2 out &&
 459                git ls-files -o >out &&
 460                test_line_count = 1 out &&
 461
 462                test_path_is_missing a &&
 463                test_path_is_file b &&
 464
 465                test_seq 0 6 >tmp &&
 466                git hash-object tmp >expect &&
 467                git rev-parse B:b >>expect &&
 468                git rev-parse >actual  \
 469                        :2:b    :3:b   &&
 470                test_cmp expect actual &&
 471
 472                # Test that the two-way merge in b is as expected
 473                git cat-file -p :2:b >>ours &&
 474                git cat-file -p :3:b >>theirs &&
 475                >empty &&
 476                test_must_fail git merge-file \
 477                        -L "HEAD" \
 478                        -L "" \
 479                        -L "B^0" \
 480                        ours empty theirs &&
 481                test_cmp ours b
 482        )
 483'
 484
 485test_expect_success 'handle rename-with-content-merge vs. add, merge other way' '
 486        (
 487                cd rename-with-content-merge-and-add &&
 488
 489                git reset --hard &&
 490                git clean -fdx &&
 491
 492                git checkout B^0 &&
 493
 494                test_must_fail git merge -s recursive A^0 >out &&
 495                test_i18ngrep "CONFLICT (rename/add)" out &&
 496
 497                git ls-files -s >out &&
 498                test_line_count = 2 out &&
 499                git ls-files -u >out &&
 500                test_line_count = 2 out &&
 501                # Also, make sure both unmerged entries are for "b"
 502                git ls-files -u b >out &&
 503                test_line_count = 2 out &&
 504                git ls-files -o >out &&
 505                test_line_count = 1 out &&
 506
 507                test_path_is_missing a &&
 508                test_path_is_file b &&
 509
 510                test_seq 0 6 >tmp &&
 511                git rev-parse B:b >expect &&
 512                git hash-object tmp >>expect &&
 513                git rev-parse >actual  \
 514                        :2:b    :3:b   &&
 515                test_cmp expect actual &&
 516
 517                # Test that the two-way merge in b is as expected
 518                git cat-file -p :2:b >>ours &&
 519                git cat-file -p :3:b >>theirs &&
 520                >empty &&
 521                test_must_fail git merge-file \
 522                        -L "HEAD" \
 523                        -L "" \
 524                        -L "A^0" \
 525                        ours empty theirs &&
 526                test_cmp ours b
 527        )
 528'
 529
 530# Test for all kinds of things that can go wrong with rename/rename (2to1):
 531#   Commit A: new files: a & b
 532#   Commit B: rename a->c, modify b
 533#   Commit C: rename b->c, modify a
 534#
 535# Merging of B & C should NOT be clean.  Questions:
 536#   * Both a & b should be removed by the merge; are they?
 537#   * The two c's should contain modifications to a & b; do they?
 538#   * The index should contain two files, both for c; does it?
 539#   * The working copy should have two files, both of form c~<unique>; does it?
 540#   * Nothing else should be present.  Is anything?
 541
 542test_expect_success 'setup rename/rename (2to1) + modify/modify' '
 543        test_create_repo rename-rename-2to1 &&
 544        (
 545                cd rename-rename-2to1 &&
 546
 547                printf "1\n2\n3\n4\n5\n" >a &&
 548                printf "5\n4\n3\n2\n1\n" >b &&
 549                git add a b &&
 550                git commit -m A &&
 551                git tag A &&
 552
 553                git checkout -b B A &&
 554                git mv a c &&
 555                echo 0 >>b &&
 556                git add b &&
 557                git commit -m B &&
 558
 559                git checkout -b C A &&
 560                git mv b c &&
 561                echo 6 >>a &&
 562                git add a &&
 563                git commit -m C
 564        )
 565'
 566
 567test_expect_success 'handle rename/rename (2to1) conflict correctly' '
 568        (
 569                cd rename-rename-2to1 &&
 570
 571                git checkout B^0 &&
 572
 573                test_must_fail git merge -s recursive C^0 >out &&
 574                test_i18ngrep "CONFLICT (rename/rename)" out &&
 575
 576                git ls-files -s >out &&
 577                test_line_count = 2 out &&
 578                git ls-files -u >out &&
 579                test_line_count = 2 out &&
 580                git ls-files -u c >out &&
 581                test_line_count = 2 out &&
 582                git ls-files -o >out &&
 583                test_line_count = 1 out &&
 584
 585                test_path_is_missing a &&
 586                test_path_is_missing b &&
 587
 588                git rev-parse >expect  \
 589                        C:a     B:b    &&
 590                git rev-parse >actual  \
 591                        :2:c    :3:c   &&
 592                test_cmp expect actual &&
 593
 594                # Test that the two-way merge in new_a is as expected
 595                git cat-file -p :2:c >>ours &&
 596                git cat-file -p :3:c >>theirs &&
 597                >empty &&
 598                test_must_fail git merge-file \
 599                        -L "HEAD" \
 600                        -L "" \
 601                        -L "C^0" \
 602                        ours empty theirs &&
 603                git hash-object c >actual &&
 604                git hash-object ours >expect &&
 605                test_cmp expect actual
 606        )
 607'
 608
 609# Testcase setup for simple rename/rename (1to2) conflict:
 610#   Commit A: new file: a
 611#   Commit B: rename a->b
 612#   Commit C: rename a->c
 613test_expect_success 'setup simple rename/rename (1to2) conflict' '
 614        test_create_repo rename-rename-1to2 &&
 615        (
 616                cd rename-rename-1to2 &&
 617
 618                echo stuff >a &&
 619                git add a &&
 620                test_tick &&
 621                git commit -m A &&
 622                git tag A &&
 623
 624                git checkout -b B A &&
 625                git mv a b &&
 626                test_tick &&
 627                git commit -m B &&
 628
 629                git checkout -b C A &&
 630                git mv a c &&
 631                test_tick &&
 632                git commit -m C
 633        )
 634'
 635
 636test_expect_success 'merge has correct working tree contents' '
 637        (
 638                cd rename-rename-1to2 &&
 639
 640                git checkout C^0 &&
 641
 642                test_must_fail git merge -s recursive B^0 &&
 643
 644                git ls-files -s >out &&
 645                test_line_count = 3 out &&
 646                git ls-files -u >out &&
 647                test_line_count = 3 out &&
 648                git ls-files -o >out &&
 649                test_line_count = 1 out &&
 650
 651                test_path_is_missing a &&
 652                git rev-parse >expect   \
 653                        A:a   A:a   A:a \
 654                        A:a   A:a       &&
 655                git rev-parse >actual    \
 656                        :1:a  :3:b  :2:c &&
 657                git hash-object >>actual \
 658                        b     c          &&
 659                test_cmp expect actual
 660        )
 661'
 662
 663# Testcase setup for rename/rename(1to2)/add-source conflict:
 664#   Commit A: new file: a
 665#   Commit B: rename a->b
 666#   Commit C: rename a->c, add completely different a
 667#
 668# Merging of B & C should NOT be clean; there's a rename/rename conflict
 669
 670test_expect_success 'setup rename/rename(1to2)/add-source conflict' '
 671        test_create_repo rename-rename-1to2-add-source-1 &&
 672        (
 673                cd rename-rename-1to2-add-source-1 &&
 674
 675                printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
 676                git add a &&
 677                git commit -m A &&
 678                git tag A &&
 679
 680                git checkout -b B A &&
 681                git mv a b &&
 682                git commit -m B &&
 683
 684                git checkout -b C A &&
 685                git mv a c &&
 686                echo something completely different >a &&
 687                git add a &&
 688                git commit -m C
 689        )
 690'
 691
 692test_expect_failure 'detect conflict with rename/rename(1to2)/add-source merge' '
 693        (
 694                cd rename-rename-1to2-add-source-1 &&
 695
 696                git checkout B^0 &&
 697
 698                test_must_fail git merge -s recursive C^0 &&
 699
 700                git ls-files -s >out &&
 701                test_line_count = 4 out &&
 702                git ls-files -o >out &&
 703                test_line_count = 1 out &&
 704
 705                git rev-parse >expect         \
 706                        C:a   A:a   B:b   C:C &&
 707                git rev-parse >actual          \
 708                        :3:a  :1:a  :2:b  :3:c &&
 709                test_cmp expect actual &&
 710
 711                test_path_is_file a &&
 712                test_path_is_file b &&
 713                test_path_is_file c
 714        )
 715'
 716
 717test_expect_success 'setup rename/rename(1to2)/add-source resolvable conflict' '
 718        test_create_repo rename-rename-1to2-add-source-2 &&
 719        (
 720                cd rename-rename-1to2-add-source-2 &&
 721
 722                >a &&
 723                git add a &&
 724                test_tick &&
 725                git commit -m base &&
 726                git tag A &&
 727
 728                git checkout -b B A &&
 729                git mv a b &&
 730                test_tick &&
 731                git commit -m one &&
 732
 733                git checkout -b C A &&
 734                git mv a b &&
 735                echo important-info >a &&
 736                git add a &&
 737                test_tick &&
 738                git commit -m two
 739        )
 740'
 741
 742test_expect_failure 'rename/rename/add-source still tracks new a file' '
 743        (
 744                cd rename-rename-1to2-add-source-2 &&
 745
 746                git checkout C^0 &&
 747                git merge -s recursive B^0 &&
 748
 749                git ls-files -s >out &&
 750                test_line_count = 2 out &&
 751                git ls-files -o >out &&
 752                test_line_count = 1 out &&
 753
 754                git rev-parse >expect \
 755                        C:a   A:a     &&
 756                git rev-parse >actual \
 757                        :0:a  :0:b    &&
 758                test_cmp expect actual
 759        )
 760'
 761
 762test_expect_success 'setup rename/rename(1to2)/add-dest conflict' '
 763        test_create_repo rename-rename-1to2-add-dest &&
 764        (
 765                cd rename-rename-1to2-add-dest &&
 766
 767                echo stuff >a &&
 768                git add a &&
 769                test_tick &&
 770                git commit -m base &&
 771                git tag A &&
 772
 773                git checkout -b B A &&
 774                git mv a b &&
 775                echo precious-data >c &&
 776                git add c &&
 777                test_tick &&
 778                git commit -m one &&
 779
 780                git checkout -b C A &&
 781                git mv a c &&
 782                echo important-info >b &&
 783                git add b &&
 784                test_tick &&
 785                git commit -m two
 786        )
 787'
 788
 789test_expect_success 'rename/rename/add-dest merge still knows about conflicting file versions' '
 790        (
 791                cd rename-rename-1to2-add-dest &&
 792
 793                git checkout C^0 &&
 794                test_must_fail git merge -s recursive B^0 &&
 795
 796                git ls-files -s >out &&
 797                test_line_count = 5 out &&
 798                git ls-files -u b >out &&
 799                test_line_count = 2 out &&
 800                git ls-files -u c >out &&
 801                test_line_count = 2 out &&
 802                git ls-files -o >out &&
 803                test_line_count = 1 out &&
 804
 805                git rev-parse >expect               \
 806                        A:a   C:b   B:b   C:c   B:c &&
 807                git rev-parse >actual                \
 808                        :1:a  :2:b  :3:b  :2:c  :3:c &&
 809                test_cmp expect actual &&
 810
 811                # Record some contents for re-doing merges
 812                git cat-file -p A:a >stuff &&
 813                git cat-file -p C:b >important_info &&
 814                git cat-file -p B:c >precious_data &&
 815                >empty &&
 816
 817                # Test the merge in b
 818                test_must_fail git merge-file \
 819                        -L "HEAD" \
 820                        -L "" \
 821                        -L "B^0" \
 822                        important_info empty stuff &&
 823                test_cmp important_info b &&
 824
 825                # Test the merge in c
 826                test_must_fail git merge-file \
 827                        -L "HEAD" \
 828                        -L "" \
 829                        -L "B^0" \
 830                        stuff empty precious_data &&
 831                test_cmp stuff c
 832        )
 833'
 834
 835# Testcase rad, rename/add/delete
 836#   Commit O: foo
 837#   Commit A: rm foo, add different bar
 838#   Commit B: rename foo->bar
 839#   Expected: CONFLICT (rename/add/delete), two-way merged bar
 840
 841test_expect_success 'rad-setup: rename/add/delete conflict' '
 842        test_create_repo rad &&
 843        (
 844                cd rad &&
 845                echo "original file" >foo &&
 846                git add foo &&
 847                git commit -m "original" &&
 848
 849                git branch O &&
 850                git branch A &&
 851                git branch B &&
 852
 853                git checkout A &&
 854                git rm foo &&
 855                echo "different file" >bar &&
 856                git add bar &&
 857                git commit -m "Remove foo, add bar" &&
 858
 859                git checkout B &&
 860                git mv foo bar &&
 861                git commit -m "rename foo to bar"
 862        )
 863'
 864
 865test_expect_failure 'rad-check: rename/add/delete conflict' '
 866        (
 867                cd rad &&
 868
 869                git checkout B^0 &&
 870                test_must_fail git merge -s recursive A^0 >out 2>err &&
 871
 872                # Not sure whether the output should contain just one
 873                # "CONFLICT (rename/add/delete)" line, or if it should break
 874                # it into a pair of "CONFLICT (rename/delete)" and
 875                # "CONFLICT (rename/add)"; allow for either.
 876                test_i18ngrep "CONFLICT (rename.*add)" out &&
 877                test_i18ngrep "CONFLICT (rename.*delete)" out &&
 878                test_must_be_empty err &&
 879
 880                git ls-files -s >file_count &&
 881                test_line_count = 2 file_count &&
 882                git ls-files -u >file_count &&
 883                test_line_count = 2 file_count &&
 884                git ls-files -o >file_count &&
 885                test_line_count = 2 file_count &&
 886
 887                git rev-parse >actual \
 888                        :2:bar :3:bar &&
 889                git rev-parse >expect \
 890                        B:bar  A:bar  &&
 891
 892                test_cmp file_is_missing foo &&
 893                # bar should have two-way merged contents of the different
 894                # versions of bar; check that content from both sides is
 895                # present.
 896                grep original bar &&
 897                grep different bar
 898        )
 899'
 900
 901# Testcase rrdd, rename/rename(2to1)/delete/delete
 902#   Commit O: foo, bar
 903#   Commit A: rename foo->baz, rm bar
 904#   Commit B: rename bar->baz, rm foo
 905#   Expected: CONFLICT (rename/rename/delete/delete), two-way merged baz
 906
 907test_expect_success 'rrdd-setup: rename/rename(2to1)/delete/delete conflict' '
 908        test_create_repo rrdd &&
 909        (
 910                cd rrdd &&
 911                echo foo >foo &&
 912                echo bar >bar &&
 913                git add foo bar &&
 914                git commit -m O &&
 915
 916                git branch O &&
 917                git branch A &&
 918                git branch B &&
 919
 920                git checkout A &&
 921                git mv foo baz &&
 922                git rm bar &&
 923                git commit -m "Rename foo, remove bar" &&
 924
 925                git checkout B &&
 926                git mv bar baz &&
 927                git rm foo &&
 928                git commit -m "Rename bar, remove foo"
 929        )
 930'
 931
 932test_expect_failure 'rrdd-check: rename/rename(2to1)/delete/delete conflict' '
 933        (
 934                cd rrdd &&
 935
 936                git checkout A^0 &&
 937                test_must_fail git merge -s recursive B^0 >out 2>err &&
 938
 939                # Not sure whether the output should contain just one
 940                # "CONFLICT (rename/rename/delete/delete)" line, or if it
 941                # should break it into three: "CONFLICT (rename/rename)" and
 942                # two "CONFLICT (rename/delete)" lines; allow for either.
 943                test_i18ngrep "CONFLICT (rename/rename)" out &&
 944                test_i18ngrep "CONFLICT (rename.*delete)" out &&
 945                test_must_be_empty err &&
 946
 947                git ls-files -s >file_count &&
 948                test_line_count = 2 file_count &&
 949                git ls-files -u >file_count &&
 950                test_line_count = 2 file_count &&
 951                git ls-files -o >file_count &&
 952                test_line_count = 2 file_count &&
 953
 954                git rev-parse >actual \
 955                        :2:baz :3:baz &&
 956                git rev-parse >expect \
 957                        O:foo  O:bar  &&
 958
 959                test_cmp file_is_missing foo &&
 960                test_cmp file_is_missing bar &&
 961                # baz should have two-way merged contents of the original
 962                # contents of foo and bar; check that content from both sides
 963                # is present.
 964                grep foo baz &&
 965                grep bar baz
 966        )
 967'
 968
 969# Testcase mod6, chains of rename/rename(1to2) and rename/rename(2to1)
 970#   Commit O: one,      three,       five
 971#   Commit A: one->two, three->four, five->six
 972#   Commit B: one->six, three->two,  five->four
 973#   Expected: six CONFLICT(rename/rename) messages, each path in two of the
 974#             multi-way merged contents found in two, four, six
 975
 976test_expect_success 'mod6-setup: chains of rename/rename(1to2) and rename/rename(2to1)' '
 977        test_create_repo mod6 &&
 978        (
 979                cd mod6 &&
 980                test_seq 11 19 >one &&
 981                test_seq 31 39 >three &&
 982                test_seq 51 59 >five &&
 983                git add . &&
 984                test_tick &&
 985                git commit -m "O" &&
 986
 987                git branch O &&
 988                git branch A &&
 989                git branch B &&
 990
 991                git checkout A &&
 992                test_seq 10 19 >one &&
 993                echo 40        >>three &&
 994                git add one three &&
 995                git mv  one   two  &&
 996                git mv  three four &&
 997                git mv  five  six  &&
 998                test_tick &&
 999                git commit -m "A" &&
1000
1001                git checkout B &&
1002                echo 20    >>one       &&
1003                echo forty >>three     &&
1004                echo 60    >>five      &&
1005                git add one three five &&
1006                git mv  one   six  &&
1007                git mv  three two  &&
1008                git mv  five  four &&
1009                test_tick &&
1010                git commit -m "B"
1011        )
1012'
1013
1014test_expect_failure 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' '
1015        (
1016                cd mod6 &&
1017
1018                git checkout A^0 &&
1019
1020                test_must_fail git merge -s recursive B^0 >out 2>err &&
1021
1022                test_i18ngrep "CONFLICT (rename/rename)" out &&
1023                test_must_be_empty err &&
1024
1025                git ls-files -s >file_count &&
1026                test_line_count = 6 file_count &&
1027                git ls-files -u >file_count &&
1028                test_line_count = 6 file_count &&
1029                git ls-files -o >file_count &&
1030                test_line_count = 3 file_count &&
1031
1032                test_seq 10 20 >merged-one &&
1033                test_seq 51 60 >merged-five &&
1034                # Determine what the merge of three would give us.
1035                test_seq 30 40 >three-side-A &&
1036                test_seq 31 39 >three-side-B &&
1037                echo forty >three-side-B &&
1038                >empty &&
1039                test_must_fail git merge-file \
1040                        -L "HEAD" \
1041                        -L "" \
1042                        -L "B^0" \
1043                        three-side-A empty three-side-B &&
1044                sed -e "s/^\([<=>]\)/\1\1\1/" three-side-A >merged-three &&
1045
1046                # Verify the index is as expected
1047                git rev-parse >actual         \
1048                        :2:two       :3:two   \
1049                        :2:four      :3:four  \
1050                        :2:six       :3:six   &&
1051                git hash-object >expect           \
1052                        merged-one   merged-three \
1053                        merged-three merged-five  \
1054                        merged-five  merged-one   &&
1055                test_cmp expect actual &&
1056
1057                git cat-file -p :2:two >expect &&
1058                git cat-file -p :3:two >other &&
1059                test_must_fail git merge-file    \
1060                        -L "HEAD"  -L ""  -L "B^0" \
1061                        expect     empty  other &&
1062                test_cmp expect two &&
1063
1064                git cat-file -p :2:four >expect &&
1065                git cat-file -p :3:four >other &&
1066                test_must_fail git merge-file    \
1067                        -L "HEAD"  -L ""  -L "B^0" \
1068                        expect     empty  other &&
1069                test_cmp expect four &&
1070
1071                git cat-file -p :2:six >expect &&
1072                git cat-file -p :3:six >other &&
1073                test_must_fail git merge-file    \
1074                        -L "HEAD"  -L ""  -L "B^0" \
1075                        expect     empty  other &&
1076                test_cmp expect six
1077        )
1078'
1079
1080test_conflicts_with_adds_and_renames() {
1081        sideL=$1
1082        sideR=$2
1083
1084        # Setup:
1085        #          L
1086        #         / \
1087        #   master   ?
1088        #         \ /
1089        #          R
1090        #
1091        # Where:
1092        #   Both L and R have files named 'three' which collide.  Each of
1093        #   the colliding files could have been involved in a rename, in
1094        #   which case there was a file named 'one' or 'two' that was
1095        #   modified on the opposite side of history and renamed into the
1096        #   collision on this side of history.
1097        #
1098        # Questions:
1099        #   1) The index should contain both a stage 2 and stage 3 entry
1100        #      for the colliding file.  Does it?
1101        #   2) When renames are involved, the content merges are clean, so
1102        #      the index should reflect the content merges, not merely the
1103        #      version of the colliding file from the prior commit.  Does
1104        #      it?
1105        #   3) There should be a file in the worktree named 'three'
1106        #      containing the two-way merged contents of the content-merged
1107        #      versions of 'three' from each of the two colliding
1108        #      files.  Is it present?
1109        #   4) There should not be any three~* files in the working
1110        #      tree
1111        test_expect_success "setup simple $sideL/$sideR conflict" '
1112                test_create_repo simple_${sideL}_${sideR} &&
1113                (
1114                        cd simple_${sideL}_${sideR} &&
1115
1116                        # Create some related files now
1117                        for i in $(test_seq 1 10)
1118                        do
1119                                echo Random base content line $i
1120                        done >file_v1 &&
1121                        cp file_v1 file_v2 &&
1122                        echo modification >>file_v2 &&
1123
1124                        cp file_v1 file_v3 &&
1125                        echo more stuff >>file_v3 &&
1126                        cp file_v3 file_v4 &&
1127                        echo yet more stuff >>file_v4 &&
1128
1129                        # Use a tag to record both these files for simple
1130                        # access, and clean out these untracked files
1131                        git tag file_v1 $(git hash-object -w file_v1) &&
1132                        git tag file_v2 $(git hash-object -w file_v2) &&
1133                        git tag file_v3 $(git hash-object -w file_v3) &&
1134                        git tag file_v4 $(git hash-object -w file_v4) &&
1135                        git clean -f &&
1136
1137                        # Setup original commit (or merge-base), consisting of
1138                        # files named "one" and "two" if renames were involved.
1139                        touch irrelevant_file &&
1140                        git add irrelevant_file &&
1141                        if [ $sideL = "rename" ]
1142                        then
1143                                git show file_v1 >one &&
1144                                git add one
1145                        fi &&
1146                        if [ $sideR = "rename" ]
1147                        then
1148                                git show file_v3 >two &&
1149                                git add two
1150                        fi &&
1151                        test_tick && git commit -m initial &&
1152
1153                        git branch L &&
1154                        git branch R &&
1155
1156                        # Handle the left side
1157                        git checkout L &&
1158                        if [ $sideL = "rename" ]
1159                        then
1160                                git mv one three
1161                        else
1162                                git show file_v2 >three &&
1163                                git add three
1164                        fi &&
1165                        if [ $sideR = "rename" ]
1166                        then
1167                                git show file_v4 >two &&
1168                                git add two
1169                        fi &&
1170                        test_tick && git commit -m L &&
1171
1172                        # Handle the right side
1173                        git checkout R &&
1174                        if [ $sideL = "rename" ]
1175                        then
1176                                git show file_v2 >one &&
1177                                git add one
1178                        fi &&
1179                        if [ $sideR = "rename" ]
1180                        then
1181                                git mv two three
1182                        else
1183                                git show file_v4 >three &&
1184                                git add three
1185                        fi &&
1186                        test_tick && git commit -m R
1187                )
1188        '
1189
1190        test_expect_success "check simple $sideL/$sideR conflict" '
1191                (
1192                        cd simple_${sideL}_${sideR} &&
1193
1194                        git checkout L^0 &&
1195
1196                        # Merge must fail; there is a conflict
1197                        test_must_fail git merge -s recursive R^0 &&
1198
1199                        # Make sure the index has the right number of entries
1200                        git ls-files -s >out &&
1201                        test_line_count = 3 out &&
1202                        git ls-files -u >out &&
1203                        test_line_count = 2 out &&
1204                        # Ensure we have the correct number of untracked files
1205                        git ls-files -o >out &&
1206                        test_line_count = 1 out &&
1207
1208                        # Nothing should have touched irrelevant_file
1209                        git rev-parse >actual      \
1210                                :0:irrelevant_file \
1211                                :2:three           \
1212                                :3:three           &&
1213                        git rev-parse >expected        \
1214                                master:irrelevant_file \
1215                                file_v2                \
1216                                file_v4                &&
1217                        test_cmp expected actual &&
1218
1219                        # Make sure we have the correct merged contents for
1220                        # three
1221                        git show file_v1 >expected &&
1222                        cat <<-\EOF >>expected &&
1223                        <<<<<<< HEAD
1224                        modification
1225                        =======
1226                        more stuff
1227                        yet more stuff
1228                        >>>>>>> R^0
1229                        EOF
1230
1231                        test_cmp expected three
1232                )
1233        '
1234}
1235
1236test_conflicts_with_adds_and_renames rename rename
1237test_conflicts_with_adds_and_renames rename add
1238test_conflicts_with_adds_and_renames add    rename
1239test_conflicts_with_adds_and_renames add    add
1240
1241# Setup:
1242#          L
1243#         / \
1244#   master   ?
1245#         \ /
1246#          R
1247#
1248# Where:
1249#   master has two files, named 'one' and 'two'.
1250#   branches L and R both modify 'one', in conflicting ways.
1251#   branches L and R both modify 'two', in conflicting ways.
1252#   branch L also renames 'one' to 'three'.
1253#   branch R also renames 'two' to 'three'.
1254#
1255#   So, we have four different conflicting files that all end up at path
1256#   'three'.
1257test_expect_success 'setup nested conflicts from rename/rename(2to1)' '
1258        test_create_repo nested_conflicts_from_rename_rename &&
1259        (
1260                cd nested_conflicts_from_rename_rename &&
1261
1262                # Create some related files now
1263                for i in $(test_seq 1 10)
1264                do
1265                        echo Random base content line $i
1266                done >file_v1 &&
1267
1268                cp file_v1 file_v2 &&
1269                cp file_v1 file_v3 &&
1270                cp file_v1 file_v4 &&
1271                cp file_v1 file_v5 &&
1272                cp file_v1 file_v6 &&
1273
1274                echo one  >>file_v1 &&
1275                echo uno  >>file_v2 &&
1276                echo eins >>file_v3 &&
1277
1278                echo two  >>file_v4 &&
1279                echo dos  >>file_v5 &&
1280                echo zwei >>file_v6 &&
1281
1282                # Setup original commit (or merge-base), consisting of
1283                # files named "one" and "two".
1284                mv file_v1 one &&
1285                mv file_v4 two &&
1286                git add one two &&
1287                test_tick && git commit -m english &&
1288
1289                git branch L &&
1290                git branch R &&
1291
1292                # Handle the left side
1293                git checkout L &&
1294                git rm one two &&
1295                mv -f file_v2 three &&
1296                mv -f file_v5 two &&
1297                git add two three &&
1298                test_tick && git commit -m spanish &&
1299
1300                # Handle the right side
1301                git checkout R &&
1302                git rm one two &&
1303                mv -f file_v3 one &&
1304                mv -f file_v6 three &&
1305                git add one three &&
1306                test_tick && git commit -m german
1307        )
1308'
1309
1310test_expect_success 'check nested conflicts from rename/rename(2to1)' '
1311        (
1312                cd nested_conflicts_from_rename_rename &&
1313
1314                git checkout L^0 &&
1315
1316                # Merge must fail; there is a conflict
1317                test_must_fail git merge -s recursive R^0 &&
1318
1319                # Make sure the index has the right number of entries
1320                git ls-files -s >out &&
1321                test_line_count = 2 out &&
1322                git ls-files -u >out &&
1323                test_line_count = 2 out &&
1324                # Ensure we have the correct number of untracked files
1325                git ls-files -o >out &&
1326                test_line_count = 1 out &&
1327
1328                # Compare :2:three to expected values
1329                git cat-file -p master:one >base &&
1330                git cat-file -p L:three >ours &&
1331                git cat-file -p R:one >theirs &&
1332                test_must_fail git merge-file    \
1333                        -L "HEAD:three"  -L ""  -L "R^0:one" \
1334                        ours             base   theirs &&
1335                sed -e "s/^\([<=>]\)/\1\1/" ours >L-three &&
1336                git cat-file -p :2:three >expect &&
1337                test_cmp expect L-three &&
1338
1339                # Compare :2:three to expected values
1340                git cat-file -p master:two >base &&
1341                git cat-file -p L:two >ours &&
1342                git cat-file -p R:three >theirs &&
1343                test_must_fail git merge-file    \
1344                        -L "HEAD:two"  -L ""  -L "R^0:three" \
1345                        ours           base   theirs &&
1346                sed -e "s/^\([<=>]\)/\1\1/" ours >R-three &&
1347                git cat-file -p :3:three >expect &&
1348                test_cmp expect R-three &&
1349
1350                # Compare three to expected contents
1351                >empty &&
1352                test_must_fail git merge-file    \
1353                        -L "HEAD"  -L ""  -L "R^0" \
1354                        L-three    empty  R-three &&
1355                test_cmp three L-three
1356        )
1357'
1358
1359test_done