t / t6042-merge-rename-corner-cases.shon commit t6036, t6042: use test_line_count instead of wc -l (0cdabc1)
   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 -f 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                test $(git rev-parse B:a) = $(git rev-parse b) &&
  84                test $(git rev-parse C:a) = $(git rev-parse a)
  85        )
  86'
  87
  88test_expect_success 'setup resolvable conflict missed if rename missed' '
  89        test_create_repo break-detection-1 &&
  90        (
  91                cd break-detection-1 &&
  92
  93                printf "1\n2\n3\n4\n5\n" >a &&
  94                echo foo >b &&
  95                git add a b &&
  96                git commit -m A &&
  97                git tag A &&
  98
  99                git checkout -b B A &&
 100                git mv a c &&
 101                echo "Completely different content" >a &&
 102                git add a &&
 103                git commit -m B &&
 104
 105                git checkout -b C A &&
 106                echo 6 >>a &&
 107                git add a &&
 108                git commit -m C
 109        )
 110'
 111
 112test_expect_failure 'conflict caused if rename not detected' '
 113        (
 114                cd break-detection-1 &&
 115
 116                git checkout -q C^0 &&
 117                git merge -s recursive B^0 &&
 118
 119                git ls-files -s >out &&
 120                test_line_count = 3 out &&
 121                git ls-files -u >out &&
 122                test_line_count = 0 out &&
 123                git ls-files -o >out &&
 124                test_line_count = 1 out &&
 125
 126                test_line_count = 6 c &&
 127                test $(git rev-parse HEAD:a) = $(git rev-parse B:a) &&
 128                test $(git rev-parse HEAD:b) = $(git rev-parse A:b)
 129        )
 130'
 131
 132test_expect_success 'setup conflict resolved wrong if rename missed' '
 133        test_create_repo break-detection-2 &&
 134        (
 135                cd break-detection-2 &&
 136
 137                printf "1\n2\n3\n4\n5\n" >a &&
 138                echo foo >b &&
 139                git add a b &&
 140                git commit -m A &&
 141                git tag A &&
 142
 143                git checkout -b D A &&
 144                echo 7 >>a &&
 145                git add a &&
 146                git mv a c &&
 147                echo "Completely different content" >a &&
 148                git add a &&
 149                git commit -m D &&
 150
 151                git checkout -b E A &&
 152                git rm a &&
 153                echo "Completely different content" >>a &&
 154                git add a &&
 155                git commit -m E
 156        )
 157'
 158
 159test_expect_failure 'missed conflict if rename not detected' '
 160        (
 161                cd break-detection-2 &&
 162
 163                git checkout -q E^0 &&
 164                test_must_fail git merge -s recursive D^0
 165        )
 166'
 167
 168# Tests for undetected rename/add-source causing a file to erroneously be
 169# deleted (and for mishandled rename/rename(1to1) causing the same issue).
 170#
 171# This test uses a rename/rename(1to1)+add-source conflict (1to1 means the
 172# same file is renamed on both sides to the same thing; it should trigger
 173# the 1to2 logic, which it would do if the add-source didn't cause issues
 174# for git's rename detection):
 175#   Commit A: new file: a
 176#   Commit B: rename a->b
 177#   Commit C: rename a->b, add unrelated a
 178
 179test_expect_success 'setup undetected rename/add-source causes data loss' '
 180        test_create_repo break-detection-3 &&
 181        (
 182                cd break-detection-3 &&
 183
 184                printf "1\n2\n3\n4\n5\n" >a &&
 185                git add a &&
 186                git commit -m A &&
 187                git tag A &&
 188
 189                git checkout -b B A &&
 190                git mv a b &&
 191                git commit -m B &&
 192
 193                git checkout -b C A &&
 194                git mv a b &&
 195                echo foobar >a &&
 196                git add a &&
 197                git commit -m C
 198        )
 199'
 200
 201test_expect_failure 'detect rename/add-source and preserve all data' '
 202        (
 203                cd break-detection-3 &&
 204
 205                git checkout B^0 &&
 206
 207                git merge -s recursive C^0 &&
 208
 209                git ls-files -s >out &&
 210                test_line_count = 2 out &&
 211                git ls-files -u >out &&
 212                test_line_count = 2 out &&
 213                git ls-files -o >out &&
 214                test_line_count = 1 out &&
 215
 216                test -f a &&
 217                test -f b &&
 218
 219                test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
 220                test $(git rev-parse HEAD:a) = $(git rev-parse C:a)
 221        )
 222'
 223
 224test_expect_failure 'detect rename/add-source and preserve all data, merge other way' '
 225        (
 226                cd break-detection-3 &&
 227
 228                git checkout C^0 &&
 229
 230                git merge -s recursive B^0 &&
 231
 232                git ls-files -s >out &&
 233                test_line_count = 2 out &&
 234                git ls-files -u >out &&
 235                test_line_count = 2 out &&
 236                git ls-files -o >out &&
 237                test_line_count = 1 out &&
 238
 239                test -f a &&
 240                test -f b &&
 241
 242                test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
 243                test $(git rev-parse HEAD:a) = $(git rev-parse C:a)
 244        )
 245'
 246
 247test_expect_success 'setup content merge + rename/directory conflict' '
 248        test_create_repo rename-directory-1 &&
 249        (
 250                cd rename-directory-1 &&
 251
 252                printf "1\n2\n3\n4\n5\n6\n" >file &&
 253                git add file &&
 254                test_tick &&
 255                git commit -m base &&
 256                git tag base &&
 257
 258                git checkout -b right &&
 259                echo 7 >>file &&
 260                mkdir newfile &&
 261                echo junk >newfile/realfile &&
 262                git add file newfile/realfile &&
 263                test_tick &&
 264                git commit -m right &&
 265
 266                git checkout -b left-conflict base &&
 267                echo 8 >>file &&
 268                git add file &&
 269                git mv file newfile &&
 270                test_tick &&
 271                git commit -m left &&
 272
 273                git checkout -b left-clean base &&
 274                echo 0 >newfile &&
 275                cat file >>newfile &&
 276                git add newfile &&
 277                git rm file &&
 278                test_tick &&
 279                git commit -m left
 280        )
 281'
 282
 283test_expect_success 'rename/directory conflict + clean content merge' '
 284        (
 285                cd rename-directory-1 &&
 286
 287                git checkout left-clean^0 &&
 288
 289                test_must_fail git merge -s recursive right^0 &&
 290
 291                git ls-files -s >out &&
 292                test_line_count = 2 out &&
 293                git ls-files -u >out &&
 294                test_line_count = 1 out &&
 295                git ls-files -o >out &&
 296                test_line_count = 2 out &&
 297
 298                echo 0 >expect &&
 299                git cat-file -p base:file >>expect &&
 300                echo 7 >>expect &&
 301                test_cmp expect newfile~HEAD &&
 302
 303                test $(git rev-parse :2:newfile) = $(git hash-object expect) &&
 304
 305                test -f newfile/realfile &&
 306                test -f newfile~HEAD
 307        )
 308'
 309
 310test_expect_success 'rename/directory conflict + content merge conflict' '
 311        (
 312                cd rename-directory-1 &&
 313
 314                git reset --hard &&
 315                git reset --hard &&
 316                git clean -fdqx &&
 317
 318                git checkout left-conflict^0 &&
 319
 320                test_must_fail git merge -s recursive right^0 &&
 321
 322                git ls-files -s >out &&
 323                test_line_count = 4 out &&
 324                git ls-files -u >out &&
 325                test_line_count = 3 out &&
 326                git ls-files -o >out &&
 327                test_line_count = 2 out &&
 328
 329                git cat-file -p left-conflict:newfile >left &&
 330                git cat-file -p base:file    >base &&
 331                git cat-file -p right:file   >right &&
 332                test_must_fail git merge-file \
 333                        -L "HEAD:newfile" \
 334                        -L "" \
 335                        -L "right^0:file" \
 336                        left base right &&
 337                test_cmp left newfile~HEAD &&
 338
 339                test $(git rev-parse :1:newfile) = $(git rev-parse base:file) &&
 340                test $(git rev-parse :2:newfile) = $(git rev-parse left-conflict:newfile) &&
 341                test $(git rev-parse :3:newfile) = $(git rev-parse right:file) &&
 342
 343                test -f newfile/realfile &&
 344                test -f newfile~HEAD
 345        )
 346'
 347
 348test_expect_success 'setup content merge + rename/directory conflict w/ disappearing dir' '
 349        test_create_repo rename-directory-2 &&
 350        (
 351                cd rename-directory-2 &&
 352
 353                mkdir sub &&
 354                printf "1\n2\n3\n4\n5\n6\n" >sub/file &&
 355                git add sub/file &&
 356                test_tick &&
 357                git commit -m base &&
 358                git tag base &&
 359
 360                git checkout -b right &&
 361                echo 7 >>sub/file &&
 362                git add sub/file &&
 363                test_tick &&
 364                git commit -m right &&
 365
 366                git checkout -b left base &&
 367                echo 0 >newfile &&
 368                cat sub/file >>newfile &&
 369                git rm sub/file &&
 370                mv newfile sub &&
 371                git add sub &&
 372                test_tick &&
 373                git commit -m left
 374        )
 375'
 376
 377test_expect_success 'disappearing dir in rename/directory conflict handled' '
 378        (
 379                cd rename-directory-2 &&
 380
 381                git checkout left^0 &&
 382
 383                git merge -s recursive right^0 &&
 384
 385                git ls-files -s >out &&
 386                test_line_count = 1 out &&
 387                git ls-files -u >out &&
 388                test_line_count = 0 out &&
 389                git ls-files -o >out &&
 390                test_line_count = 1 out &&
 391
 392                echo 0 >expect &&
 393                git cat-file -p base:sub/file >>expect &&
 394                echo 7 >>expect &&
 395                test_cmp expect sub &&
 396
 397                test -f sub
 398        )
 399'
 400
 401# Test for all kinds of things that can go wrong with rename/rename (2to1):
 402#   Commit A: new files: a & b
 403#   Commit B: rename a->c, modify b
 404#   Commit C: rename b->c, modify a
 405#
 406# Merging of B & C should NOT be clean.  Questions:
 407#   * Both a & b should be removed by the merge; are they?
 408#   * The two c's should contain modifications to a & b; do they?
 409#   * The index should contain two files, both for c; does it?
 410#   * The working copy should have two files, both of form c~<unique>; does it?
 411#   * Nothing else should be present.  Is anything?
 412
 413test_expect_success 'setup rename/rename (2to1) + modify/modify' '
 414        test_create_repo rename-rename-2to1 &&
 415        (
 416                cd rename-rename-2to1 &&
 417
 418                printf "1\n2\n3\n4\n5\n" >a &&
 419                printf "5\n4\n3\n2\n1\n" >b &&
 420                git add a b &&
 421                git commit -m A &&
 422                git tag A &&
 423
 424                git checkout -b B A &&
 425                git mv a c &&
 426                echo 0 >>b &&
 427                git add b &&
 428                git commit -m B &&
 429
 430                git checkout -b C A &&
 431                git mv b c &&
 432                echo 6 >>a &&
 433                git add a &&
 434                git commit -m C
 435        )
 436'
 437
 438test_expect_success 'handle rename/rename (2to1) conflict correctly' '
 439        (
 440                cd rename-rename-2to1 &&
 441
 442                git checkout B^0 &&
 443
 444                test_must_fail git merge -s recursive C^0 >out &&
 445                test_i18ngrep "CONFLICT (rename/rename)" out &&
 446
 447                git ls-files -s >out &&
 448                test_line_count = 2 out &&
 449                git ls-files -u >out &&
 450                test_line_count = 2 out &&
 451                git ls-files -u c >out &&
 452                test_line_count = 2 out &&
 453                git ls-files -o >out &&
 454                test_line_count = 3 out &&
 455
 456                test ! -f a &&
 457                test ! -f b &&
 458                test -f c~HEAD &&
 459                test -f c~C^0 &&
 460
 461                test $(git hash-object c~HEAD) = $(git rev-parse C:a) &&
 462                test $(git hash-object c~C^0) = $(git rev-parse B:b)
 463        )
 464'
 465
 466# Testcase setup for simple rename/rename (1to2) conflict:
 467#   Commit A: new file: a
 468#   Commit B: rename a->b
 469#   Commit C: rename a->c
 470test_expect_success 'setup simple rename/rename (1to2) conflict' '
 471        test_create_repo rename-rename-1to2 &&
 472        (
 473                cd rename-rename-1to2 &&
 474
 475                echo stuff >a &&
 476                git add a &&
 477                test_tick &&
 478                git commit -m A &&
 479                git tag A &&
 480
 481                git checkout -b B A &&
 482                git mv a b &&
 483                test_tick &&
 484                git commit -m B &&
 485
 486                git checkout -b C A &&
 487                git mv a c &&
 488                test_tick &&
 489                git commit -m C
 490        )
 491'
 492
 493test_expect_success 'merge has correct working tree contents' '
 494        (
 495                cd rename-rename-1to2 &&
 496
 497                git checkout C^0 &&
 498
 499                test_must_fail git merge -s recursive B^0 &&
 500
 501                git ls-files -s >out &&
 502                test_line_count = 3 out &&
 503                git ls-files -u >out &&
 504                test_line_count = 3 out &&
 505                git ls-files -o >out &&
 506                test_line_count = 1 out &&
 507
 508                test $(git rev-parse :1:a) = $(git rev-parse A:a) &&
 509                test $(git rev-parse :3:b) = $(git rev-parse A:a) &&
 510                test $(git rev-parse :2:c) = $(git rev-parse A:a) &&
 511
 512                test ! -f a &&
 513                test $(git hash-object b) = $(git rev-parse A:a) &&
 514                test $(git hash-object c) = $(git rev-parse A:a)
 515        )
 516'
 517
 518# Testcase setup for rename/rename(1to2)/add-source conflict:
 519#   Commit A: new file: a
 520#   Commit B: rename a->b
 521#   Commit C: rename a->c, add completely different a
 522#
 523# Merging of B & C should NOT be clean; there's a rename/rename conflict
 524
 525test_expect_success 'setup rename/rename(1to2)/add-source conflict' '
 526        test_create_repo rename-rename-1to2-add-source-1 &&
 527        (
 528                cd rename-rename-1to2-add-source-1 &&
 529
 530                printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
 531                git add a &&
 532                git commit -m A &&
 533                git tag A &&
 534
 535                git checkout -b B A &&
 536                git mv a b &&
 537                git commit -m B &&
 538
 539                git checkout -b C A &&
 540                git mv a c &&
 541                echo something completely different >a &&
 542                git add a &&
 543                git commit -m C
 544        )
 545'
 546
 547test_expect_failure 'detect conflict with rename/rename(1to2)/add-source merge' '
 548        (
 549                cd rename-rename-1to2-add-source-1 &&
 550
 551                git checkout B^0 &&
 552
 553                test_must_fail git merge -s recursive C^0 &&
 554
 555                git ls-files -s >out &&
 556                test_line_count = 4 out &&
 557                git ls-files -o >out &&
 558                test_line_count = 1 out &&
 559
 560                test $(git rev-parse 3:a) = $(git rev-parse C:a) &&
 561                test $(git rev-parse 1:a) = $(git rev-parse A:a) &&
 562                test $(git rev-parse 2:b) = $(git rev-parse B:b) &&
 563                test $(git rev-parse 3:c) = $(git rev-parse C:c) &&
 564
 565                test -f a &&
 566                test -f b &&
 567                test -f c
 568        )
 569'
 570
 571test_expect_success 'setup rename/rename(1to2)/add-source resolvable conflict' '
 572        test_create_repo rename-rename-1to2-add-source-2 &&
 573        (
 574                cd rename-rename-1to2-add-source-2 &&
 575
 576                >a &&
 577                git add a &&
 578                test_tick &&
 579                git commit -m base &&
 580                git tag A &&
 581
 582                git checkout -b B A &&
 583                git mv a b &&
 584                test_tick &&
 585                git commit -m one &&
 586
 587                git checkout -b C A &&
 588                git mv a b &&
 589                echo important-info >a &&
 590                git add a &&
 591                test_tick &&
 592                git commit -m two
 593        )
 594'
 595
 596test_expect_failure 'rename/rename/add-source still tracks new a file' '
 597        (
 598                cd rename-rename-1to2-add-source-2 &&
 599
 600                git checkout C^0 &&
 601                git merge -s recursive B^0 &&
 602
 603                git ls-files -s >out &&
 604                test_line_count = 2 out &&
 605                git ls-files -o >out &&
 606                test_line_count = 1 out &&
 607
 608                test $(git rev-parse HEAD:a) = $(git rev-parse C:a) &&
 609                test $(git rev-parse HEAD:b) = $(git rev-parse A:a)
 610        )
 611'
 612
 613test_expect_success 'setup rename/rename(1to2)/add-dest conflict' '
 614        test_create_repo rename-rename-1to2-add-dest &&
 615        (
 616                cd rename-rename-1to2-add-dest &&
 617
 618                echo stuff >a &&
 619                git add a &&
 620                test_tick &&
 621                git commit -m base &&
 622                git tag A &&
 623
 624                git checkout -b B A &&
 625                git mv a b &&
 626                echo precious-data >c &&
 627                git add c &&
 628                test_tick &&
 629                git commit -m one &&
 630
 631                git checkout -b C A &&
 632                git mv a c &&
 633                echo important-info >b &&
 634                git add b &&
 635                test_tick &&
 636                git commit -m two
 637        )
 638'
 639
 640test_expect_success 'rename/rename/add-dest merge still knows about conflicting file versions' '
 641        (
 642                cd rename-rename-1to2-add-dest &&
 643
 644                git checkout C^0 &&
 645                test_must_fail git merge -s recursive B^0 &&
 646
 647                git ls-files -s >out &&
 648                test_line_count = 5 out &&
 649                git ls-files -u b >out &&
 650                test_line_count = 2 out &&
 651                git ls-files -u c >out &&
 652                test_line_count = 2 out &&
 653                git ls-files -o >out &&
 654                test_line_count = 5 out &&
 655
 656                test $(git rev-parse :1:a) = $(git rev-parse A:a) &&
 657                test $(git rev-parse :2:b) = $(git rev-parse C:b) &&
 658                test $(git rev-parse :3:b) = $(git rev-parse B:b) &&
 659                test $(git rev-parse :2:c) = $(git rev-parse C:c) &&
 660                test $(git rev-parse :3:c) = $(git rev-parse B:c) &&
 661
 662                test $(git hash-object c~HEAD) = $(git rev-parse C:c) &&
 663                test $(git hash-object c~B\^0) = $(git rev-parse B:c) &&
 664                test $(git hash-object b~HEAD) = $(git rev-parse C:b) &&
 665                test $(git hash-object b~B\^0) = $(git rev-parse B:b) &&
 666
 667                test ! -f b &&
 668                test ! -f c
 669        )
 670'
 671
 672test_done