t / t6036-recursive-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 involving criss-cross merges'
   4
   5. ./test-lib.sh
   6
   7get_clean_checkout () {
   8        git reset --hard &&
   9        git clean -fdqx &&
  10        git checkout "$1"
  11}
  12
  13#
  14#  L1  L2
  15#   o---o
  16#  / \ / \
  17# o   X   ?
  18#  \ / \ /
  19#   o---o
  20#  R1  R2
  21#
  22
  23test_expect_success 'setup basic criss-cross + rename with no modifications' '
  24        test_create_repo basic-rename &&
  25        (
  26                cd basic-rename &&
  27
  28                ten="0 1 2 3 4 5 6 7 8 9" &&
  29                for i in $ten
  30                do
  31                        echo line $i in a sample file
  32                done >one &&
  33                for i in $ten
  34                do
  35                        echo line $i in another sample file
  36                done >two &&
  37                git add one two &&
  38                test_tick && git commit -m initial &&
  39
  40                git branch L1 &&
  41                git checkout -b R1 &&
  42                git mv one three &&
  43                test_tick && git commit -m R1 &&
  44
  45                git checkout L1 &&
  46                git mv two three &&
  47                test_tick && git commit -m L1 &&
  48
  49                git checkout L1^0 &&
  50                test_tick && git merge -s ours R1 &&
  51                git tag L2 &&
  52
  53                git checkout R1^0 &&
  54                test_tick && git merge -s ours L1 &&
  55                git tag R2
  56        )
  57'
  58
  59test_expect_success 'merge simple rename+criss-cross with no modifications' '
  60        (
  61                cd basic-rename &&
  62
  63                git reset --hard &&
  64                git checkout L2^0 &&
  65
  66                test_must_fail git merge -s recursive R2^0 &&
  67
  68                git ls-files -s >out &&
  69                test_line_count = 2 out &&
  70                git ls-files -u >out &&
  71                test_line_count = 2 out &&
  72                git ls-files -o >out &&
  73                test_line_count = 3 out &&
  74
  75                test $(git rev-parse :2:three) = $(git rev-parse L2:three) &&
  76                test $(git rev-parse :3:three) = $(git rev-parse R2:three) &&
  77
  78                test $(git rev-parse L2:three) = $(git hash-object three~HEAD) &&
  79                test $(git rev-parse R2:three) = $(git hash-object three~R2^0)
  80        )
  81'
  82
  83#
  84# Same as before, but modify L1 slightly:
  85#
  86#  L1m L2
  87#   o---o
  88#  / \ / \
  89# o   X   ?
  90#  \ / \ /
  91#   o---o
  92#  R1  R2
  93#
  94
  95test_expect_success 'setup criss-cross + rename merges with basic modification' '
  96        test_create_repo rename-modify &&
  97        (
  98                cd rename-modify &&
  99
 100                ten="0 1 2 3 4 5 6 7 8 9" &&
 101                for i in $ten
 102                do
 103                        echo line $i in a sample file
 104                done >one &&
 105                for i in $ten
 106                do
 107                        echo line $i in another sample file
 108                done >two &&
 109                git add one two &&
 110                test_tick && git commit -m initial &&
 111
 112                git branch L1 &&
 113                git checkout -b R1 &&
 114                git mv one three &&
 115                echo more >>two &&
 116                git add two &&
 117                test_tick && git commit -m R1 &&
 118
 119                git checkout L1 &&
 120                git mv two three &&
 121                test_tick && git commit -m L1 &&
 122
 123                git checkout L1^0 &&
 124                test_tick && git merge -s ours R1 &&
 125                git tag L2 &&
 126
 127                git checkout R1^0 &&
 128                test_tick && git merge -s ours L1 &&
 129                git tag R2
 130        )
 131'
 132
 133test_expect_success 'merge criss-cross + rename merges with basic modification' '
 134        (
 135                cd rename-modify &&
 136
 137                git checkout L2^0 &&
 138
 139                test_must_fail git merge -s recursive R2^0 &&
 140
 141                git ls-files -s >out &&
 142                test_line_count = 2 out &&
 143                git ls-files -u >out &&
 144                test_line_count = 2 out &&
 145                git ls-files -o >out &&
 146                test_line_count = 3 out &&
 147
 148                test $(git rev-parse :2:three) = $(git rev-parse L2:three) &&
 149                test $(git rev-parse :3:three) = $(git rev-parse R2:three) &&
 150
 151                test $(git rev-parse L2:three) = $(git hash-object three~HEAD) &&
 152                test $(git rev-parse R2:three) = $(git hash-object three~R2^0)
 153        )
 154'
 155
 156#
 157# For the next test, we start with three commits in two lines of development
 158# which setup a rename/add conflict:
 159#   Commit A: File 'a' exists
 160#   Commit B: Rename 'a' -> 'new_a'
 161#   Commit C: Modify 'a', create different 'new_a'
 162# Later, two different people merge and resolve differently:
 163#   Commit D: Merge B & C, ignoring separately created 'new_a'
 164#   Commit E: Merge B & C making use of some piece of secondary 'new_a'
 165# Finally, someone goes to merge D & E.  Does git detect the conflict?
 166#
 167#      B   D
 168#      o---o
 169#     / \ / \
 170#  A o   X   ? F
 171#     \ / \ /
 172#      o---o
 173#      C   E
 174#
 175
 176test_expect_success 'setup differently handled merges of rename/add conflict' '
 177        test_create_repo rename-add &&
 178        (
 179                cd rename-add &&
 180
 181                printf "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n" >a &&
 182                git add a &&
 183                test_tick && git commit -m A &&
 184
 185                git branch B &&
 186                git checkout -b C &&
 187                echo 10 >>a &&
 188                echo "other content" >>new_a &&
 189                git add a new_a &&
 190                test_tick && git commit -m C &&
 191
 192                git checkout B &&
 193                git mv a new_a &&
 194                test_tick && git commit -m B &&
 195
 196                git checkout B^0 &&
 197                test_must_fail git merge C &&
 198                git clean -f &&
 199                test_tick && git commit -m D &&
 200                git tag D &&
 201
 202                git checkout C^0 &&
 203                test_must_fail git merge B &&
 204                rm new_a~HEAD new_a &&
 205                printf "Incorrectly merged content" >>new_a &&
 206                git add -u &&
 207                test_tick && git commit -m E &&
 208                git tag E
 209        )
 210'
 211
 212test_expect_success 'git detects differently handled merges conflict' '
 213        (
 214                cd rename-add &&
 215
 216                git checkout D^0 &&
 217
 218                test_must_fail git merge -s recursive E^0 &&
 219
 220                git ls-files -s >out &&
 221                test_line_count = 3 out &&
 222                git ls-files -u >out &&
 223                test_line_count = 3 out &&
 224                git ls-files -o >out &&
 225                test_line_count = 1 out &&
 226
 227                test $(git rev-parse :2:new_a) = $(git rev-parse D:new_a) &&
 228                test $(git rev-parse :3:new_a) = $(git rev-parse E:new_a) &&
 229
 230                git cat-file -p B:new_a >>merged &&
 231                git cat-file -p C:new_a >>merge-me &&
 232                >empty &&
 233                test_must_fail git merge-file \
 234                        -L "Temporary merge branch 2" \
 235                        -L "" \
 236                        -L "Temporary merge branch 1" \
 237                        merged empty merge-me &&
 238                sed -e "s/^\([<=>]\)/\1\1\1/" merged >merged-internal &&
 239                test $(git rev-parse :1:new_a) = $(git hash-object merged-internal)
 240        )
 241'
 242
 243#
 244# criss-cross + modify/delete:
 245#
 246#      B   D
 247#      o---o
 248#     / \ / \
 249#  A o   X   ? F
 250#     \ / \ /
 251#      o---o
 252#      C   E
 253#
 254#   Commit A: file with contents 'A\n'
 255#   Commit B: file with contents 'B\n'
 256#   Commit C: file not present
 257#   Commit D: file with contents 'B\n'
 258#   Commit E: file not present
 259#
 260# Merging commits D & E should result in modify/delete conflict.
 261
 262test_expect_success 'setup criss-cross + modify/delete resolved differently' '
 263        test_create_repo modify-delete &&
 264        (
 265                cd modify-delete &&
 266
 267                echo A >file &&
 268                git add file &&
 269                test_tick &&
 270                git commit -m A &&
 271
 272                git branch B &&
 273                git checkout -b C &&
 274                git rm file &&
 275                test_tick &&
 276                git commit -m C &&
 277
 278                git checkout B &&
 279                echo B >file &&
 280                git add file &&
 281                test_tick &&
 282                git commit -m B &&
 283
 284                git checkout B^0 &&
 285                test_must_fail git merge C &&
 286                echo B >file &&
 287                git add file &&
 288                test_tick &&
 289                git commit -m D &&
 290                git tag D &&
 291
 292                git checkout C^0 &&
 293                test_must_fail git merge B &&
 294                git rm file &&
 295                test_tick &&
 296                git commit -m E &&
 297                git tag E
 298        )
 299'
 300
 301test_expect_success 'git detects conflict merging criss-cross+modify/delete' '
 302        (
 303                cd modify-delete &&
 304
 305                git checkout D^0 &&
 306
 307                test_must_fail git merge -s recursive E^0 &&
 308
 309                git ls-files -s >out &&
 310                test_line_count = 2 out &&
 311                git ls-files -u >out &&
 312                test_line_count = 2 out &&
 313
 314                test $(git rev-parse :1:file) = $(git rev-parse master:file) &&
 315                test $(git rev-parse :2:file) = $(git rev-parse B:file)
 316        )
 317'
 318
 319test_expect_success 'git detects conflict merging criss-cross+modify/delete, reverse direction' '
 320        (
 321                cd modify-delete &&
 322
 323                git reset --hard &&
 324                git checkout E^0 &&
 325
 326                test_must_fail git merge -s recursive D^0 &&
 327
 328                git ls-files -s >out &&
 329                test_line_count = 2 out &&
 330                git ls-files -u >out &&
 331                test_line_count = 2 out &&
 332
 333                test $(git rev-parse :1:file) = $(git rev-parse master:file) &&
 334                test $(git rev-parse :3:file) = $(git rev-parse B:file)
 335        )
 336'
 337
 338#
 339# criss-cross + d/f conflict via add/add:
 340#   Commit A: Neither file 'a' nor directory 'a/' exists.
 341#   Commit B: Introduce 'a'
 342#   Commit C: Introduce 'a/file'
 343#   Commit D: Merge B & C, keeping 'a' and deleting 'a/'
 344#
 345# Two different later cases:
 346#   Commit E1: Merge B & C, deleting 'a' but keeping 'a/file'
 347#   Commit E2: Merge B & C, deleting 'a' but keeping a slightly modified 'a/file'
 348#
 349#      B   D
 350#      o---o
 351#     / \ / \
 352#  A o   X   ? F
 353#     \ / \ /
 354#      o---o
 355#      C   E1 or E2
 356#
 357# Merging D & E1 requires we first create a virtual merge base X from
 358# merging A & B in memory.  Now, if X could keep both 'a' and 'a/file' in
 359# the index, then the merge of D & E1 could be resolved cleanly with both
 360# 'a' and 'a/file' removed.  Since git does not currently allow creating
 361# such a tree, the best we can do is have X contain both 'a~<unique>' and
 362# 'a/file' resulting in the merge of D and E1 having a rename/delete
 363# conflict for 'a'.  (Although this merge appears to be unsolvable with git
 364# currently, git could do a lot better than it currently does with these
 365# d/f conflicts, which is the purpose of this test.)
 366#
 367# Merge of D & E2 has similar issues for path 'a', but should always result
 368# in a modify/delete conflict for path 'a/file'.
 369#
 370# We run each merge in both directions, to check for directional issues
 371# with D/F conflict handling.
 372#
 373
 374test_expect_success 'setup differently handled merges of directory/file conflict' '
 375        test_create_repo directory-file &&
 376        (
 377                cd directory-file &&
 378
 379                >ignore-me &&
 380                git add ignore-me &&
 381                test_tick &&
 382                git commit -m A &&
 383                git tag A &&
 384
 385                git branch B &&
 386                git checkout -b C &&
 387                mkdir a &&
 388                echo 10 >a/file &&
 389                git add a/file &&
 390                test_tick &&
 391                git commit -m C &&
 392
 393                git checkout B &&
 394                echo 5 >a &&
 395                git add a &&
 396                test_tick &&
 397                git commit -m B &&
 398
 399                git checkout B^0 &&
 400                test_must_fail git merge C &&
 401                git clean -f &&
 402                rm -rf a/ &&
 403                echo 5 >a &&
 404                git add a &&
 405                test_tick &&
 406                git commit -m D &&
 407                git tag D &&
 408
 409                git checkout C^0 &&
 410                test_must_fail git merge B &&
 411                git clean -f &&
 412                git rm --cached a &&
 413                echo 10 >a/file &&
 414                git add a/file &&
 415                test_tick &&
 416                git commit -m E1 &&
 417                git tag E1 &&
 418
 419                git checkout C^0 &&
 420                test_must_fail git merge B &&
 421                git clean -f &&
 422                git rm --cached a &&
 423                printf "10\n11\n" >a/file &&
 424                git add a/file &&
 425                test_tick &&
 426                git commit -m E2 &&
 427                git tag E2
 428        )
 429'
 430
 431test_expect_success 'merge of D & E1 fails but has appropriate contents' '
 432        (
 433                cd directory-file &&
 434
 435                get_clean_checkout D^0 &&
 436
 437                test_must_fail git merge -s recursive E1^0 &&
 438
 439                git ls-files -s >out &&
 440                test_line_count = 2 out &&
 441                git ls-files -u >out &&
 442                test_line_count = 1 out &&
 443                git ls-files -o >out &&
 444                test_line_count = 1 out &&
 445
 446                test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
 447                test $(git rev-parse :2:a) = $(git rev-parse B:a)
 448        )
 449'
 450
 451test_expect_success 'merge of E1 & D fails but has appropriate contents' '
 452        (
 453                cd directory-file &&
 454
 455                get_clean_checkout E1^0 &&
 456
 457                test_must_fail git merge -s recursive D^0 &&
 458
 459                git ls-files -s >out &&
 460                test_line_count = 2 out &&
 461                git ls-files -u >out &&
 462                test_line_count = 1 out &&
 463                git ls-files -o >out &&
 464                test_line_count = 1 out &&
 465
 466                test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
 467                test $(git rev-parse :3:a) = $(git rev-parse B:a)
 468        )
 469'
 470
 471test_expect_success 'merge of D & E2 fails but has appropriate contents' '
 472        (
 473                cd directory-file &&
 474
 475                get_clean_checkout D^0 &&
 476
 477                test_must_fail git merge -s recursive E2^0 &&
 478
 479                git ls-files -s >out &&
 480                test_line_count = 4 out &&
 481                git ls-files -u >out &&
 482                test_line_count = 3 out &&
 483                git ls-files -o >out &&
 484                test_line_count = 2 out &&
 485
 486                test $(git rev-parse :2:a) = $(git rev-parse B:a) &&
 487                test $(git rev-parse :3:a/file) = $(git rev-parse E2:a/file) &&
 488                test $(git rev-parse :1:a/file) = $(git rev-parse C:a/file) &&
 489                test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
 490
 491                test -f a~HEAD
 492        )
 493'
 494
 495test_expect_success 'merge of E2 & D fails but has appropriate contents' '
 496        (
 497                cd directory-file &&
 498
 499                get_clean_checkout E2^0 &&
 500
 501                test_must_fail git merge -s recursive D^0 &&
 502
 503                git ls-files -s >out &&
 504                test_line_count = 4 out &&
 505                git ls-files -u >out &&
 506                test_line_count = 3 out &&
 507                git ls-files -o >out &&
 508                test_line_count = 2 out &&
 509
 510                test $(git rev-parse :3:a) = $(git rev-parse B:a) &&
 511                test $(git rev-parse :2:a/file) = $(git rev-parse E2:a/file) &&
 512                test $(git rev-parse :1:a/file) = $(git rev-parse C:a/file) &&
 513                test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
 514
 515                test -f a~D^0
 516        )
 517'
 518
 519#
 520# criss-cross with rename/rename(1to2)/modify followed by
 521# rename/rename(2to1)/modify:
 522#
 523#      B   D
 524#      o---o
 525#     / \ / \
 526#  A o   X   ? F
 527#     \ / \ /
 528#      o---o
 529#      C   E
 530#
 531#   Commit A: new file: a
 532#   Commit B: rename a->b, modifying by adding a line
 533#   Commit C: rename a->c
 534#   Commit D: merge B&C, resolving conflict by keeping contents in newname
 535#   Commit E: merge B&C, resolving conflict similar to D but adding another line
 536#
 537# There is a conflict merging B & C, but one of filename not of file
 538# content.  Whoever created D and E chose specific resolutions for that
 539# conflict resolution.  Now, since: (1) there is no content conflict
 540# merging B & C, (2) D does not modify that merged content further, and (3)
 541# both D & E resolve the name conflict in the same way, the modification to
 542# newname in E should not cause any conflicts when it is merged with D.
 543# (Note that this can be accomplished by having the virtual merge base have
 544# the merged contents of b and c stored in a file named a, which seems like
 545# the most logical choice anyway.)
 546#
 547# Comment from Junio: I do not necessarily agree with the choice "a", but
 548# it feels sound to say "B and C do not agree what the final pathname
 549# should be, but we know this content was derived from the common A:a so we
 550# use one path whose name is arbitrary in the virtual merge base X between
 551# D and E" and then further let the rename detection to notice that that
 552# arbitrary path gets renamed between X-D to "newname" and X-E also to
 553# "newname" to resolve it as both sides renaming it to the same new
 554# name. It is akin to what we do at the content level, i.e. "B and C do not
 555# agree what the final contents should be, so we leave the conflict marker
 556# but that may cancel out at the final merge stage".
 557
 558test_expect_success 'setup rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' '
 559        test_create_repo rename-squared-squared &&
 560        (
 561                cd rename-squared-squared &&
 562
 563                printf "1\n2\n3\n4\n5\n6\n" >a &&
 564                git add a &&
 565                git commit -m A &&
 566                git tag A &&
 567
 568                git checkout -b B A &&
 569                git mv a b &&
 570                echo 7 >>b &&
 571                git add -u &&
 572                git commit -m B &&
 573
 574                git checkout -b C A &&
 575                git mv a c &&
 576                git commit -m C &&
 577
 578                git checkout -q B^0 &&
 579                git merge --no-commit -s ours C^0 &&
 580                git mv b newname &&
 581                git commit -m "Merge commit C^0 into HEAD" &&
 582                git tag D &&
 583
 584                git checkout -q C^0 &&
 585                git merge --no-commit -s ours B^0 &&
 586                git mv c newname &&
 587                printf "7\n8\n" >>newname &&
 588                git add -u &&
 589                git commit -m "Merge commit B^0 into HEAD" &&
 590                git tag E
 591        )
 592'
 593
 594test_expect_success 'handle rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' '
 595        (
 596                cd rename-squared-squared &&
 597
 598                git checkout D^0 &&
 599
 600                git merge -s recursive E^0 &&
 601
 602                git ls-files -s >out &&
 603                test_line_count = 1 out &&
 604                git ls-files -u >out &&
 605                test_line_count = 0 out &&
 606                git ls-files -o >out &&
 607                test_line_count = 1 out &&
 608
 609                test $(git rev-parse HEAD:newname) = $(git rev-parse E:newname)
 610        )
 611'
 612
 613#
 614# criss-cross with rename/rename(1to2)/add-source + resolvable modify/modify:
 615#
 616#      B   D
 617#      o---o
 618#     / \ / \
 619#  A o   X   ? F
 620#     \ / \ /
 621#      o---o
 622#      C   E
 623#
 624#   Commit A: new file: a
 625#   Commit B: rename a->b
 626#   Commit C: rename a->c, add different a
 627#   Commit D: merge B&C, keeping b&c and (new) a modified at beginning
 628#   Commit E: merge B&C, keeping b&c and (new) a modified at end
 629#
 630# Merging commits D & E should result in no conflict; doing so correctly
 631# requires getting the virtual merge base (from merging B&C) right, handling
 632# renaming carefully (both in the virtual merge base and later), and getting
 633# content merge handled.
 634
 635test_expect_success 'setup criss-cross + rename/rename/add-source + modify/modify' '
 636        test_create_repo rename-rename-add-source &&
 637        (
 638                cd rename-rename-add-source &&
 639
 640                printf "lots\nof\nwords\nand\ncontent\n" >a &&
 641                git add a &&
 642                git commit -m A &&
 643                git tag A &&
 644
 645                git checkout -b B A &&
 646                git mv a b &&
 647                git commit -m B &&
 648
 649                git checkout -b C A &&
 650                git mv a c &&
 651                printf "2\n3\n4\n5\n6\n7\n" >a &&
 652                git add a &&
 653                git commit -m C &&
 654
 655                git checkout B^0 &&
 656                git merge --no-commit -s ours C^0 &&
 657                git checkout C -- a c &&
 658                mv a old_a &&
 659                echo 1 >a &&
 660                cat old_a >>a &&
 661                rm old_a &&
 662                git add -u &&
 663                git commit -m "Merge commit C^0 into HEAD" &&
 664                git tag D &&
 665
 666                git checkout C^0 &&
 667                git merge --no-commit -s ours B^0 &&
 668                git checkout B -- b &&
 669                echo 8 >>a &&
 670                git add -u &&
 671                git commit -m "Merge commit B^0 into HEAD" &&
 672                git tag E
 673        )
 674'
 675
 676test_expect_failure 'detect rename/rename/add-source for virtual merge-base' '
 677        (
 678                cd rename-rename-add-source &&
 679
 680                git checkout D^0 &&
 681
 682                git merge -s recursive E^0 &&
 683
 684                git ls-files -s >out &&
 685                test_line_count = 3 out &&
 686                git ls-files -u >out &&
 687                test_line_count = 0 out &&
 688                git ls-files -o >out &&
 689                test_line_count = 1 out &&
 690
 691                test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
 692                test $(git rev-parse HEAD:c) = $(git rev-parse A:a) &&
 693                test "$(cat a)" = "$(printf "1\n2\n3\n4\n5\n6\n7\n8\n")"
 694        )
 695'
 696
 697#
 698# criss-cross with rename/rename(1to2)/add-dest + simple modify:
 699#
 700#      B   D
 701#      o---o
 702#     / \ / \
 703#  A o   X   ? F
 704#     \ / \ /
 705#      o---o
 706#      C   E
 707#
 708#   Commit A: new file: a
 709#   Commit B: rename a->b, add c
 710#   Commit C: rename a->c
 711#   Commit D: merge B&C, keeping A:a and B:c
 712#   Commit E: merge B&C, keeping A:a and slightly modified c from B
 713#
 714# Merging commits D & E should result in no conflict.  The virtual merge
 715# base of B & C needs to not delete B:c for that to work, though...
 716
 717test_expect_success 'setup criss-cross+rename/rename/add-dest + simple modify' '
 718        test_create_repo rename-rename-add-dest &&
 719        (
 720                cd rename-rename-add-dest &&
 721
 722                >a &&
 723                git add a &&
 724                git commit -m A &&
 725                git tag A &&
 726
 727                git checkout -b B A &&
 728                git mv a b &&
 729                printf "1\n2\n3\n4\n5\n6\n7\n" >c &&
 730                git add c &&
 731                git commit -m B &&
 732
 733                git checkout -b C A &&
 734                git mv a c &&
 735                git commit -m C &&
 736
 737                git checkout B^0 &&
 738                git merge --no-commit -s ours C^0 &&
 739                git mv b a &&
 740                git commit -m "D is like B but renames b back to a" &&
 741                git tag D &&
 742
 743                git checkout B^0 &&
 744                git merge --no-commit -s ours C^0 &&
 745                git mv b a &&
 746                echo 8 >>c &&
 747                git add c &&
 748                git commit -m "E like D but has mod in c" &&
 749                git tag E
 750        )
 751'
 752
 753test_expect_success 'virtual merge base handles rename/rename(1to2)/add-dest' '
 754        (
 755                cd rename-rename-add-dest &&
 756
 757                git checkout D^0 &&
 758
 759                git merge -s recursive E^0 &&
 760
 761                git ls-files -s >out &&
 762                test_line_count = 2 out &&
 763                git ls-files -u >out &&
 764                test_line_count = 0 out &&
 765                git ls-files -o >out &&
 766                test_line_count = 1 out &&
 767
 768                test $(git rev-parse HEAD:a) = $(git rev-parse A:a) &&
 769                test $(git rev-parse HEAD:c) = $(git rev-parse E:c)
 770        )
 771'
 772
 773test_done