t / t6046-merge-skip-unneeded-updates.shon commit upload-pack: support hidden refs with protocol v2 (e20b419)
   1#!/bin/sh
   2
   3test_description="merge cases"
   4
   5# The setup for all of them, pictorially, is:
   6#
   7#      A
   8#      o
   9#     / \
  10#  O o   ?
  11#     \ /
  12#      o
  13#      B
  14#
  15# To help make it easier to follow the flow of tests, they have been
  16# divided into sections and each test will start with a quick explanation
  17# of what commits O, A, and B contain.
  18#
  19# Notation:
  20#    z/{b,c}   means  files z/b and z/c both exist
  21#    x/d_1     means  file x/d exists with content d1.  (Purpose of the
  22#                     underscore notation is to differentiate different
  23#                     files that might be renamed into each other's paths.)
  24
  25. ./test-lib.sh
  26
  27
  28###########################################################################
  29# SECTION 1: Cases involving no renames (one side has subset of changes of
  30#            the other side)
  31###########################################################################
  32
  33# Testcase 1a, Changes on A, subset of changes on B
  34#   Commit O: b_1
  35#   Commit A: b_2
  36#   Commit B: b_3
  37#   Expected: b_2
  38
  39test_expect_success '1a-setup: Modify(A)/Modify(B), change on B subset of A' '
  40        test_create_repo 1a &&
  41        (
  42                cd 1a &&
  43
  44                test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
  45                git add b &&
  46                test_tick &&
  47                git commit -m "O" &&
  48
  49                git branch O &&
  50                git branch A &&
  51                git branch B &&
  52
  53                git checkout A &&
  54                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
  55                git add b &&
  56                test_tick &&
  57                git commit -m "A" &&
  58
  59                git checkout B &&
  60                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
  61                git add b &&
  62                test_tick &&
  63                git commit -m "B"
  64        )
  65'
  66
  67test_expect_success '1a-check-L: Modify(A)/Modify(B), change on B subset of A' '
  68        test_when_finished "git -C 1a reset --hard" &&
  69        test_when_finished "git -C 1a clean -fd" &&
  70        (
  71                cd 1a &&
  72
  73                git checkout A^0 &&
  74
  75                test-tool chmtime =31337 b &&
  76                test-tool chmtime -v +0 b >expected-mtime &&
  77
  78                GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
  79
  80                test_i18ngrep "Skipped b" out &&
  81                test_must_be_empty err &&
  82
  83                test-tool chmtime -v +0 b >actual-mtime &&
  84                test_cmp expected-mtime actual-mtime &&
  85
  86                git ls-files -s >index_files &&
  87                test_line_count = 1 index_files &&
  88
  89                git rev-parse >actual HEAD:b &&
  90                git rev-parse >expect A:b &&
  91                test_cmp expect actual &&
  92
  93                git hash-object b   >actual &&
  94                git rev-parse   A:b >expect &&
  95                test_cmp expect actual
  96        )
  97'
  98
  99test_expect_success '1a-check-R: Modify(A)/Modify(B), change on B subset of A' '
 100        test_when_finished "git -C 1a reset --hard" &&
 101        test_when_finished "git -C 1a clean -fd" &&
 102        (
 103                cd 1a &&
 104
 105                git checkout B^0 &&
 106
 107                GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
 108
 109                test_i18ngrep "Auto-merging b" out &&
 110                test_must_be_empty err &&
 111
 112                git ls-files -s >index_files &&
 113                test_line_count = 1 index_files &&
 114
 115                git rev-parse >actual HEAD:b &&
 116                git rev-parse >expect A:b &&
 117                test_cmp expect actual &&
 118
 119                git hash-object b   >actual &&
 120                git rev-parse   A:b >expect &&
 121                test_cmp expect actual
 122        )
 123'
 124
 125
 126###########################################################################
 127# SECTION 2: Cases involving basic renames
 128###########################################################################
 129
 130# Testcase 2a, Changes on A, rename on B
 131#   Commit O: b_1
 132#   Commit A: b_2
 133#   Commit B: c_1
 134#   Expected: c_2
 135
 136test_expect_success '2a-setup: Modify(A)/rename(B)' '
 137        test_create_repo 2a &&
 138        (
 139                cd 2a &&
 140
 141                test_seq 1 10 >b &&
 142                git add b &&
 143                test_tick &&
 144                git commit -m "O" &&
 145
 146                git branch O &&
 147                git branch A &&
 148                git branch B &&
 149
 150                git checkout A &&
 151                test_seq 1 11 >b &&
 152                git add b &&
 153                test_tick &&
 154                git commit -m "A" &&
 155
 156                git checkout B &&
 157                git mv b c &&
 158                test_tick &&
 159                git commit -m "B"
 160        )
 161'
 162
 163test_expect_success '2a-check-L: Modify/rename, merge into modify side' '
 164        test_when_finished "git -C 2a reset --hard" &&
 165        test_when_finished "git -C 2a clean -fd" &&
 166        (
 167                cd 2a &&
 168
 169                git checkout A^0 &&
 170
 171                GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
 172
 173                test_i18ngrep ! "Skipped c" out &&
 174                test_must_be_empty err &&
 175
 176                git ls-files -s >index_files &&
 177                test_line_count = 1 index_files &&
 178
 179                git rev-parse >actual HEAD:c &&
 180                git rev-parse >expect A:b &&
 181                test_cmp expect actual &&
 182
 183                git hash-object c   >actual &&
 184                git rev-parse   A:b >expect &&
 185                test_cmp expect actual &&
 186
 187                test_must_fail git rev-parse HEAD:b &&
 188                test_path_is_missing b
 189        )
 190'
 191
 192test_expect_success '2a-check-R: Modify/rename, merge into rename side' '
 193        test_when_finished "git -C 2a reset --hard" &&
 194        test_when_finished "git -C 2a clean -fd" &&
 195        (
 196                cd 2a &&
 197
 198                git checkout B^0 &&
 199
 200                GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
 201
 202                test_i18ngrep ! "Skipped c" out &&
 203                test_must_be_empty err &&
 204
 205                git ls-files -s >index_files &&
 206                test_line_count = 1 index_files &&
 207
 208                git rev-parse >actual HEAD:c &&
 209                git rev-parse >expect A:b &&
 210                test_cmp expect actual &&
 211
 212                git hash-object c   >actual &&
 213                git rev-parse   A:b >expect &&
 214                test_cmp expect actual &&
 215
 216                test_must_fail git rev-parse HEAD:b &&
 217                test_path_is_missing b
 218        )
 219'
 220
 221# Testcase 2b, Changed and renamed on A, subset of changes on B
 222#   Commit O: b_1
 223#   Commit A: c_2
 224#   Commit B: b_3
 225#   Expected: c_2
 226
 227test_expect_success '2b-setup: Rename+Mod(A)/Mod(B), B mods subset of A' '
 228        test_create_repo 2b &&
 229        (
 230                cd 2b &&
 231
 232                test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
 233                git add b &&
 234                test_tick &&
 235                git commit -m "O" &&
 236
 237                git branch O &&
 238                git branch A &&
 239                git branch B &&
 240
 241                git checkout A &&
 242                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
 243                git add b &&
 244                git mv b c &&
 245                test_tick &&
 246                git commit -m "A" &&
 247
 248                git checkout B &&
 249                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
 250                git add b &&
 251                test_tick &&
 252                git commit -m "B"
 253        )
 254'
 255
 256test_expect_success '2b-check-L: Rename+Mod(A)/Mod(B), B mods subset of A' '
 257        test_when_finished "git -C 2b reset --hard" &&
 258        test_when_finished "git -C 2b clean -fd" &&
 259        (
 260                cd 2b &&
 261
 262                git checkout A^0 &&
 263
 264                test-tool chmtime =31337 c &&
 265                test-tool chmtime -v +0 c >expected-mtime &&
 266
 267                GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
 268
 269                test_i18ngrep "Skipped c" out &&
 270                test_must_be_empty err &&
 271
 272                test-tool chmtime -v +0 c >actual-mtime &&
 273                test_cmp expected-mtime actual-mtime &&
 274
 275                git ls-files -s >index_files &&
 276                test_line_count = 1 index_files &&
 277
 278                git rev-parse >actual HEAD:c &&
 279                git rev-parse >expect A:c &&
 280                test_cmp expect actual &&
 281
 282                git hash-object c   >actual &&
 283                git rev-parse   A:c >expect &&
 284                test_cmp expect actual &&
 285
 286                test_must_fail git rev-parse HEAD:b &&
 287                test_path_is_missing b
 288        )
 289'
 290
 291test_expect_success '2b-check-R: Rename+Mod(A)/Mod(B), B mods subset of A' '
 292        test_when_finished "git -C 2b reset --hard" &&
 293        test_when_finished "git -C 2b clean -fd" &&
 294        (
 295                cd 2b &&
 296
 297                git checkout B^0 &&
 298
 299                GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
 300
 301                test_i18ngrep "Auto-merging c" out &&
 302                test_must_be_empty err &&
 303
 304                git ls-files -s >index_files &&
 305                test_line_count = 1 index_files &&
 306
 307                git rev-parse >actual HEAD:c &&
 308                git rev-parse >expect A:c &&
 309                test_cmp expect actual &&
 310
 311                git hash-object c   >actual &&
 312                git rev-parse   A:c >expect &&
 313                test_cmp expect actual &&
 314
 315                test_must_fail git rev-parse HEAD:b &&
 316                test_path_is_missing b
 317        )
 318'
 319
 320# Testcase 2c, Changes on A, rename on B
 321#   Commit O: b_1
 322#   Commit A: b_2, c_3
 323#   Commit B: c_1
 324#   Expected: rename/add conflict c_2 vs c_3
 325#
 326#   NOTE: Since A modified b_1->b_2, and B renamed b_1->c_1, the threeway
 327#         merge of those files should result in c_2.  We then should have a
 328#         rename/add conflict between c_2 and c_3.  However, if we note in
 329#         merge_content() that A had the right contents (b_2 has same
 330#         contents as c_2, just at a different name), and that A had the
 331#         right path present (c_3 existed) and thus decides that it can
 332#         skip the update, then we're in trouble.  This test verifies we do
 333#         not make that particular mistake.
 334
 335test_expect_success '2c-setup: Modify b & add c VS rename b->c' '
 336        test_create_repo 2c &&
 337        (
 338                cd 2c &&
 339
 340                test_seq 1 10 >b &&
 341                git add b &&
 342                test_tick &&
 343                git commit -m "O" &&
 344
 345                git branch O &&
 346                git branch A &&
 347                git branch B &&
 348
 349                git checkout A &&
 350                test_seq 1 11 >b &&
 351                echo whatever >c &&
 352                git add b c &&
 353                test_tick &&
 354                git commit -m "A" &&
 355
 356                git checkout B &&
 357                git mv b c &&
 358                test_tick &&
 359                git commit -m "B"
 360        )
 361'
 362
 363test_expect_success '2c-check: Modify b & add c VS rename b->c' '
 364        (
 365                cd 2c &&
 366
 367                git checkout A^0 &&
 368
 369                GIT_MERGE_VERBOSITY=3 &&
 370                export GIT_MERGE_VERBOSITY &&
 371                test_must_fail git merge -s recursive B^0 >out 2>err &&
 372
 373                test_i18ngrep "CONFLICT (rename/add): Rename b->c" out &&
 374                test_i18ngrep ! "Skipped c" out &&
 375                test_must_be_empty err
 376
 377                # FIXME: rename/add conflicts are horribly broken right now;
 378                # when I get back to my patch series fixing it and
 379                # rename/rename(2to1) conflicts to bring them in line with
 380                # how add/add conflicts behave, then checks like the below
 381                # could be added.  But that patch series is waiting until
 382                # the rename-directory-detection series lands, which this
 383                # is part of.  And in the mean time, I do not want to further
 384                # enforce broken behavior.  So for now, the main test is the
 385                # one above that err is an empty file.
 386
 387                #git ls-files -s >index_files &&
 388                #test_line_count = 2 index_files &&
 389
 390                #git rev-parse >actual :2:c :3:c &&
 391                #git rev-parse >expect A:b  A:c  &&
 392                #test_cmp expect actual &&
 393
 394                #git cat-file -p A:b >>merged &&
 395                #git cat-file -p A:c >>merge-me &&
 396                #>empty &&
 397                #test_must_fail git merge-file \
 398                #       -L "Temporary merge branch 1" \
 399                #       -L "" \
 400                #       -L "Temporary merge branch 2" \
 401                #       merged empty merge-me &&
 402                #sed -e "s/^\([<=>]\)/\1\1\1/" merged >merged-internal &&
 403
 404                #git hash-object c               >actual &&
 405                #git hash-object merged-internal >expect &&
 406                #test_cmp expect actual &&
 407
 408                #test_path_is_missing b
 409        )
 410'
 411
 412
 413###########################################################################
 414# SECTION 3: Cases involving directory renames
 415#
 416# NOTE:
 417#   Directory renames only apply when one side renames a directory, and the
 418#   other side adds or renames a path into that directory.  Applying the
 419#   directory rename to that new path creates a new pathname that didn't
 420#   exist on either side of history.  Thus, it is impossible for the
 421#   merge contents to already be at the right path, so all of these checks
 422#   exist just to make sure that updates are not skipped.
 423###########################################################################
 424
 425# Testcase 3a, Change + rename into dir foo on A, dir rename foo->bar on B
 426#   Commit O: bq_1, foo/whatever
 427#   Commit A: foo/{bq_2, whatever}
 428#   Commit B: bq_1, bar/whatever
 429#   Expected: bar/{bq_2, whatever}
 430
 431test_expect_success '3a-setup: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
 432        test_create_repo 3a &&
 433        (
 434                cd 3a &&
 435
 436                mkdir foo &&
 437                test_seq 1 10 >bq &&
 438                test_write_lines a b c d e f g h i j k >foo/whatever &&
 439                git add bq foo/whatever &&
 440                test_tick &&
 441                git commit -m "O" &&
 442
 443                git branch O &&
 444                git branch A &&
 445                git branch B &&
 446
 447                git checkout A &&
 448                test_seq 1 11 >bq &&
 449                git add bq &&
 450                git mv bq foo/ &&
 451                test_tick &&
 452                git commit -m "A" &&
 453
 454                git checkout B &&
 455                git mv foo/ bar/ &&
 456                test_tick &&
 457                git commit -m "B"
 458        )
 459'
 460
 461test_expect_success '3a-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
 462        test_when_finished "git -C 3a reset --hard" &&
 463        test_when_finished "git -C 3a clean -fd" &&
 464        (
 465                cd 3a &&
 466
 467                git checkout A^0 &&
 468
 469                GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
 470
 471                test_i18ngrep ! "Skipped bar/bq" out &&
 472                test_must_be_empty err &&
 473
 474                git ls-files -s >index_files &&
 475                test_line_count = 2 index_files &&
 476
 477                git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
 478                git rev-parse >expect A:foo/bq    A:foo/whatever &&
 479                test_cmp expect actual &&
 480
 481                git hash-object bar/bq   bar/whatever   >actual &&
 482                git rev-parse   A:foo/bq A:foo/whatever >expect &&
 483                test_cmp expect actual &&
 484
 485                test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
 486                test_path_is_missing bq foo/bq foo/whatever
 487        )
 488'
 489
 490test_expect_success '3a-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
 491        test_when_finished "git -C 3a reset --hard" &&
 492        test_when_finished "git -C 3a clean -fd" &&
 493        (
 494                cd 3a &&
 495
 496                git checkout B^0 &&
 497
 498                GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
 499
 500                test_i18ngrep ! "Skipped bar/bq" out &&
 501                test_must_be_empty err &&
 502
 503                git ls-files -s >index_files &&
 504                test_line_count = 2 index_files &&
 505
 506                git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
 507                git rev-parse >expect A:foo/bq    A:foo/whatever &&
 508                test_cmp expect actual &&
 509
 510                git hash-object bar/bq   bar/whatever   >actual &&
 511                git rev-parse   A:foo/bq A:foo/whatever >expect &&
 512                test_cmp expect actual &&
 513
 514                test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
 515                test_path_is_missing bq foo/bq foo/whatever
 516        )
 517'
 518
 519# Testcase 3b, rename into dir foo on A, dir rename foo->bar + change on B
 520#   Commit O: bq_1, foo/whatever
 521#   Commit A: foo/{bq_1, whatever}
 522#   Commit B: bq_2, bar/whatever
 523#   Expected: bar/{bq_2, whatever}
 524
 525test_expect_success '3b-setup: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
 526        test_create_repo 3b &&
 527        (
 528                cd 3b &&
 529
 530                mkdir foo &&
 531                test_seq 1 10 >bq &&
 532                test_write_lines a b c d e f g h i j k >foo/whatever &&
 533                git add bq foo/whatever &&
 534                test_tick &&
 535                git commit -m "O" &&
 536
 537                git branch O &&
 538                git branch A &&
 539                git branch B &&
 540
 541                git checkout A &&
 542                git mv bq foo/ &&
 543                test_tick &&
 544                git commit -m "A" &&
 545
 546                git checkout B &&
 547                test_seq 1 11 >bq &&
 548                git add bq &&
 549                git mv foo/ bar/ &&
 550                test_tick &&
 551                git commit -m "B"
 552        )
 553'
 554
 555test_expect_success '3b-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
 556        test_when_finished "git -C 3b reset --hard" &&
 557        test_when_finished "git -C 3b clean -fd" &&
 558        (
 559                cd 3b &&
 560
 561                git checkout A^0 &&
 562
 563                GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
 564
 565                test_i18ngrep ! "Skipped bar/bq" out &&
 566                test_must_be_empty err &&
 567
 568                git ls-files -s >index_files &&
 569                test_line_count = 2 index_files &&
 570
 571                git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
 572                git rev-parse >expect B:bq        A:foo/whatever &&
 573                test_cmp expect actual &&
 574
 575                git hash-object bar/bq bar/whatever   >actual &&
 576                git rev-parse   B:bq   A:foo/whatever >expect &&
 577                test_cmp expect actual &&
 578
 579                test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
 580                test_path_is_missing bq foo/bq foo/whatever
 581        )
 582'
 583
 584test_expect_success '3b-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
 585        test_when_finished "git -C 3b reset --hard" &&
 586        test_when_finished "git -C 3b clean -fd" &&
 587        (
 588                cd 3b &&
 589
 590                git checkout B^0 &&
 591
 592                GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
 593
 594                test_i18ngrep ! "Skipped bar/bq" out &&
 595                test_must_be_empty err &&
 596
 597                git ls-files -s >index_files &&
 598                test_line_count = 2 index_files &&
 599
 600                git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
 601                git rev-parse >expect B:bq        A:foo/whatever &&
 602                test_cmp expect actual &&
 603
 604                git hash-object bar/bq bar/whatever   >actual &&
 605                git rev-parse   B:bq   A:foo/whatever >expect &&
 606                test_cmp expect actual &&
 607
 608                test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
 609                test_path_is_missing bq foo/bq foo/whatever
 610        )
 611'
 612
 613###########################################################################
 614# SECTION 4: Cases involving dirty changes
 615###########################################################################
 616
 617# Testcase 4a, Changed on A, subset of changes on B, locally modified
 618#   Commit O: b_1
 619#   Commit A: b_2
 620#   Commit B: b_3
 621#   Working copy: b_4
 622#   Expected: b_2 for merge, b_4 in working copy
 623
 624test_expect_success '4a-setup: Change on A, change on B subset of A, dirty mods present' '
 625        test_create_repo 4a &&
 626        (
 627                cd 4a &&
 628
 629                test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
 630                git add b &&
 631                test_tick &&
 632                git commit -m "O" &&
 633
 634                git branch O &&
 635                git branch A &&
 636                git branch B &&
 637
 638                git checkout A &&
 639                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
 640                git add b &&
 641                test_tick &&
 642                git commit -m "A" &&
 643
 644                git checkout B &&
 645                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
 646                git add b &&
 647                test_tick &&
 648                git commit -m "B"
 649        )
 650'
 651
 652# NOTE: For as long as we continue using unpack_trees() without index_only
 653#   set to true, it will error out on a case like this claiming the the locally
 654#   modified file would be overwritten by the merge.  Getting this testcase
 655#   correct requires doing the merge in-memory first, then realizing that no
 656#   updates to the file are necessary, and thus that we can just leave the path
 657#   alone.
 658test_expect_failure '4a-check: Change on A, change on B subset of A, dirty mods present' '
 659        test_when_finished "git -C 4a reset --hard" &&
 660        test_when_finished "git -C 4a clean -fd" &&
 661        (
 662                cd 4a &&
 663
 664                git checkout A^0 &&
 665                echo "File rewritten" >b &&
 666
 667                test-tool chmtime =31337 b &&
 668                test-tool chmtime -v +0 b >expected-mtime &&
 669
 670                GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
 671
 672                test_i18ngrep "Skipped b" out &&
 673                test_must_be_empty err &&
 674
 675                test-tool chmtime -v +0 b >actual-mtime &&
 676                test_cmp expected-mtime actual-mtime &&
 677
 678                git ls-files -s >index_files &&
 679                test_line_count = 1 index_files &&
 680
 681                git rev-parse >actual :0:b &&
 682                git rev-parse >expect A:b &&
 683                test_cmp expect actual &&
 684
 685                git hash-object b >actual &&
 686                echo "File rewritten" | git hash-object --stdin >expect &&
 687                test_cmp expect actual
 688        )
 689'
 690
 691# Testcase 4b, Changed+renamed on A, subset of changes on B, locally modified
 692#   Commit O: b_1
 693#   Commit A: c_2
 694#   Commit B: b_3
 695#   Working copy: c_4
 696#   Expected: c_2
 697
 698test_expect_success '4b-setup: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mods present' '
 699        test_create_repo 4b &&
 700        (
 701                cd 4b &&
 702
 703                test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
 704                git add b &&
 705                test_tick &&
 706                git commit -m "O" &&
 707
 708                git branch O &&
 709                git branch A &&
 710                git branch B &&
 711
 712                git checkout A &&
 713                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
 714                git add b &&
 715                git mv b c &&
 716                test_tick &&
 717                git commit -m "A" &&
 718
 719                git checkout B &&
 720                test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
 721                git add b &&
 722                test_tick &&
 723                git commit -m "B"
 724        )
 725'
 726
 727test_expect_success '4b-check: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mods present' '
 728        test_when_finished "git -C 4b reset --hard" &&
 729        test_when_finished "git -C 4b clean -fd" &&
 730        (
 731                cd 4b &&
 732
 733                git checkout A^0 &&
 734                echo "File rewritten" >c &&
 735
 736                test-tool chmtime =31337 c &&
 737                test-tool chmtime -v +0 c >expected-mtime &&
 738
 739                GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
 740
 741                test_i18ngrep "Skipped c" out &&
 742                test_must_be_empty err &&
 743
 744                test-tool chmtime -v +0 c >actual-mtime &&
 745                test_cmp expected-mtime actual-mtime &&
 746
 747                git ls-files -s >index_files &&
 748                test_line_count = 1 index_files &&
 749
 750                git rev-parse >actual :0:c &&
 751                git rev-parse >expect A:c &&
 752                test_cmp expect actual &&
 753
 754                git hash-object c >actual &&
 755                echo "File rewritten" | git hash-object --stdin >expect &&
 756                test_cmp expect actual &&
 757
 758                test_must_fail git rev-parse HEAD:b &&
 759                test_path_is_missing b
 760        )
 761'
 762
 763test_done