1#!/bin/sh 2 3test_description='merge-recursive backend test' 4 5GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 6export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 7 8. ./test-lib.sh 9. "$TEST_DIRECTORY"/lib-merge.sh 10 11test_expect_success 'setup 1' ' 12 13 echo hello >a && 14 o0=$(git hash-object a) && 15 cp a b && 16 cp a c && 17 mkdir d && 18 cp a d/e && 19 20 test_tick && 21 git add a b c d/e && 22 git commit -m initial && 23 c0=$(git rev-parse --verify HEAD) && 24 git branch side && 25 git branch df-1 && 26 git branch df-2 && 27 git branch df-3 && 28 git branch remove && 29 git branch submod && 30 git branch copy && 31 git branch rename && 32 git branch rename-ln && 33 34 echo hello >>a && 35 cp a d/e && 36 o1=$(git hash-object a) && 37 38 git add a d/e && 39 40 test_tick && 41 git commit -m "main modifies a and d/e" && 42 c1=$(git rev-parse --verify HEAD) && 43 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 44 ( 45 echo "100644 blob $o1 a" && 46 echo "100644 blob $o0 b" && 47 echo "100644 blob $o0 c" && 48 echo "100644 blob $o1 d/e" && 49 echo "100644 $o1 0 a" && 50 echo "100644 $o0 0 b" && 51 echo "100644 $o0 0 c" && 52 echo "100644 $o1 0 d/e" 53 ) >expected && 54 test_cmp expected actual 55' 56 57test_expect_success 'setup 2' ' 58 59 rm -rf [abcd] && 60 git checkout side && 61 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 62 ( 63 echo "100644 blob $o0 a" && 64 echo "100644 blob $o0 b" && 65 echo "100644 blob $o0 c" && 66 echo "100644 blob $o0 d/e" && 67 echo "100644 $o0 0 a" && 68 echo "100644 $o0 0 b" && 69 echo "100644 $o0 0 c" && 70 echo "100644 $o0 0 d/e" 71 ) >expected && 72 test_cmp expected actual && 73 74 echo goodbye >>a && 75 o2=$(git hash-object a) && 76 77 git add a && 78 79 test_tick && 80 git commit -m "side modifies a" && 81 c2=$(git rev-parse --verify HEAD) && 82 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 83 ( 84 echo "100644 blob $o2 a" && 85 echo "100644 blob $o0 b" && 86 echo "100644 blob $o0 c" && 87 echo "100644 blob $o0 d/e" && 88 echo "100644 $o2 0 a" && 89 echo "100644 $o0 0 b" && 90 echo "100644 $o0 0 c" && 91 echo "100644 $o0 0 d/e" 92 ) >expected && 93 test_cmp expected actual 94' 95 96test_expect_success 'setup 3' ' 97 98 rm -rf [abcd] && 99 git checkout df-1 && 100 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 101 ( 102 echo "100644 blob $o0 a" && 103 echo "100644 blob $o0 b" && 104 echo "100644 blob $o0 c" && 105 echo "100644 blob $o0 d/e" && 106 echo "100644 $o0 0 a" && 107 echo "100644 $o0 0 b" && 108 echo "100644 $o0 0 c" && 109 echo "100644 $o0 0 d/e" 110 ) >expected && 111 test_cmp expected actual && 112 113 rm -f b && mkdir b && echo df-1 >b/c && git add b/c && 114 o3=$(git hash-object b/c) && 115 116 test_tick && 117 git commit -m "df-1 makes b/c" && 118 c3=$(git rev-parse --verify HEAD) && 119 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 120 ( 121 echo "100644 blob $o0 a" && 122 echo "100644 blob $o3 b/c" && 123 echo "100644 blob $o0 c" && 124 echo "100644 blob $o0 d/e" && 125 echo "100644 $o0 0 a" && 126 echo "100644 $o3 0 b/c" && 127 echo "100644 $o0 0 c" && 128 echo "100644 $o0 0 d/e" 129 ) >expected && 130 test_cmp expected actual 131' 132 133test_expect_success 'setup 4' ' 134 135 rm -rf [abcd] && 136 git checkout df-2 && 137 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 138 ( 139 echo "100644 blob $o0 a" && 140 echo "100644 blob $o0 b" && 141 echo "100644 blob $o0 c" && 142 echo "100644 blob $o0 d/e" && 143 echo "100644 $o0 0 a" && 144 echo "100644 $o0 0 b" && 145 echo "100644 $o0 0 c" && 146 echo "100644 $o0 0 d/e" 147 ) >expected && 148 test_cmp expected actual && 149 150 rm -f a && mkdir a && echo df-2 >a/c && git add a/c && 151 o4=$(git hash-object a/c) && 152 153 test_tick && 154 git commit -m "df-2 makes a/c" && 155 c4=$(git rev-parse --verify HEAD) && 156 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 157 ( 158 echo "100644 blob $o4 a/c" && 159 echo "100644 blob $o0 b" && 160 echo "100644 blob $o0 c" && 161 echo "100644 blob $o0 d/e" && 162 echo "100644 $o4 0 a/c" && 163 echo "100644 $o0 0 b" && 164 echo "100644 $o0 0 c" && 165 echo "100644 $o0 0 d/e" 166 ) >expected && 167 test_cmp expected actual 168' 169 170test_expect_success 'setup 5' ' 171 172 rm -rf [abcd] && 173 git checkout remove && 174 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 175 ( 176 echo "100644 blob $o0 a" && 177 echo "100644 blob $o0 b" && 178 echo "100644 blob $o0 c" && 179 echo "100644 blob $o0 d/e" && 180 echo "100644 $o0 0 a" && 181 echo "100644 $o0 0 b" && 182 echo "100644 $o0 0 c" && 183 echo "100644 $o0 0 d/e" 184 ) >expected && 185 test_cmp expected actual && 186 187 rm -f b && 188 echo remove-conflict >a && 189 190 git add a && 191 git rm b && 192 o5=$(git hash-object a) && 193 194 test_tick && 195 git commit -m "remove removes b and modifies a" && 196 c5=$(git rev-parse --verify HEAD) && 197 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 198 ( 199 echo "100644 blob $o5 a" && 200 echo "100644 blob $o0 c" && 201 echo "100644 blob $o0 d/e" && 202 echo "100644 $o5 0 a" && 203 echo "100644 $o0 0 c" && 204 echo "100644 $o0 0 d/e" 205 ) >expected && 206 test_cmp expected actual 207 208' 209 210test_expect_success 'setup 6' ' 211 212 rm -rf [abcd] && 213 git checkout df-3 && 214 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 215 ( 216 echo "100644 blob $o0 a" && 217 echo "100644 blob $o0 b" && 218 echo "100644 blob $o0 c" && 219 echo "100644 blob $o0 d/e" && 220 echo "100644 $o0 0 a" && 221 echo "100644 $o0 0 b" && 222 echo "100644 $o0 0 c" && 223 echo "100644 $o0 0 d/e" 224 ) >expected && 225 test_cmp expected actual && 226 227 rm -fr d && echo df-3 >d && git add d && 228 o6=$(git hash-object d) && 229 230 test_tick && 231 git commit -m "df-3 makes d" && 232 c6=$(git rev-parse --verify HEAD) && 233 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 234 ( 235 echo "100644 blob $o0 a" && 236 echo "100644 blob $o0 b" && 237 echo "100644 blob $o0 c" && 238 echo "100644 blob $o6 d" && 239 echo "100644 $o0 0 a" && 240 echo "100644 $o0 0 b" && 241 echo "100644 $o0 0 c" && 242 echo "100644 $o6 0 d" 243 ) >expected && 244 test_cmp expected actual 245' 246 247test_expect_success 'setup 7' ' 248 249 git checkout submod && 250 git rm d/e && 251 test_tick && 252 git commit -m "remove d/e" && 253 git update-index --add --cacheinfo 160000 $c1 d && 254 test_tick && 255 git commit -m "make d/ a submodule" 256' 257 258test_expect_success 'setup 8' ' 259 git checkout rename && 260 git mv a e && 261 git add e && 262 test_tick && 263 git commit -m "rename a->e" && 264 c7=$(git rev-parse --verify HEAD) && 265 git checkout rename-ln && 266 git mv a e && 267 test_ln_s_add e a && 268 test_tick && 269 git commit -m "rename a->e, symlink a->e" && 270 oln=$(printf e | git hash-object --stdin) 271' 272 273test_expect_success 'setup 9' ' 274 git checkout copy && 275 cp a e && 276 git add e && 277 test_tick && 278 git commit -m "copy a->e" 279' 280 281test_expect_success 'merge-recursive simple' ' 282 283 rm -fr [abcd] && 284 git checkout -f "$c2" && 285 286 test_expect_code 1 git merge-recursive "$c0" -- "$c2" "$c1" 287' 288 289test_expect_success 'merge-recursive result' ' 290 291 git ls-files -s >actual && 292 ( 293 echo "100644 $o0 1 a" && 294 echo "100644 $o2 2 a" && 295 echo "100644 $o1 3 a" && 296 echo "100644 $o0 0 b" && 297 echo "100644 $o0 0 c" && 298 echo "100644 $o1 0 d/e" 299 ) >expected && 300 test_cmp expected actual 301 302' 303 304test_expect_success 'fail if the index has unresolved entries' ' 305 306 rm -fr [abcd] && 307 git checkout -f "$c1" && 308 309 test_must_fail git merge "$c5" && 310 test_must_fail git merge "$c5" 2> out && 311 test_i18ngrep "not possible because you have unmerged files" out && 312 git add -u && 313 test_must_fail git merge "$c5" 2> out && 314 test_i18ngrep "You have not concluded your merge" out && 315 rm -f .git/MERGE_HEAD && 316 test_must_fail git merge "$c5" 2> out && 317 test_i18ngrep "Your local changes to the following files would be overwritten by merge:" out 318' 319 320test_expect_success 'merge-recursive remove conflict' ' 321 322 rm -fr [abcd] && 323 git checkout -f "$c1" && 324 325 test_expect_code 1 git merge-recursive "$c0" -- "$c1" "$c5" 326' 327 328test_expect_success 'merge-recursive remove conflict' ' 329 330 git ls-files -s >actual && 331 ( 332 echo "100644 $o0 1 a" && 333 echo "100644 $o1 2 a" && 334 echo "100644 $o5 3 a" && 335 echo "100644 $o0 0 c" && 336 echo "100644 $o1 0 d/e" 337 ) >expected && 338 test_cmp expected actual 339 340' 341 342test_expect_success 'merge-recursive d/f simple' ' 343 rm -fr [abcd] && 344 git reset --hard && 345 git checkout -f "$c1" && 346 347 git merge-recursive "$c0" -- "$c1" "$c3" 348' 349 350test_expect_success 'merge-recursive result' ' 351 352 git ls-files -s >actual && 353 ( 354 echo "100644 $o1 0 a" && 355 echo "100644 $o3 0 b/c" && 356 echo "100644 $o0 0 c" && 357 echo "100644 $o1 0 d/e" 358 ) >expected && 359 test_cmp expected actual 360 361' 362 363test_expect_success 'merge-recursive d/f conflict' ' 364 365 rm -fr [abcd] && 366 git reset --hard && 367 git checkout -f "$c1" && 368 369 test_expect_code 1 git merge-recursive "$c0" -- "$c1" "$c4" 370' 371 372test_expect_success 'merge-recursive d/f conflict result' ' 373 374 git ls-files -s >actual && 375 ( 376 echo "100644 $o0 1 a" && 377 echo "100644 $o1 2 a" && 378 echo "100644 $o4 0 a/c" && 379 echo "100644 $o0 0 b" && 380 echo "100644 $o0 0 c" && 381 echo "100644 $o1 0 d/e" 382 ) >expected && 383 test_cmp expected actual 384 385' 386 387test_expect_success 'merge-recursive d/f conflict the other way' ' 388 389 rm -fr [abcd] && 390 git reset --hard && 391 git checkout -f "$c4" && 392 393 test_expect_code 1 git merge-recursive "$c0" -- "$c4" "$c1" 394' 395 396test_expect_success 'merge-recursive d/f conflict result the other way' ' 397 398 git ls-files -s >actual && 399 ( 400 echo "100644 $o0 1 a" && 401 echo "100644 $o1 3 a" && 402 echo "100644 $o4 0 a/c" && 403 echo "100644 $o0 0 b" && 404 echo "100644 $o0 0 c" && 405 echo "100644 $o1 0 d/e" 406 ) >expected && 407 test_cmp expected actual 408 409' 410 411test_expect_success 'merge-recursive d/f conflict' ' 412 413 rm -fr [abcd] && 414 git reset --hard && 415 git checkout -f "$c1" && 416 417 test_expect_code 1 git merge-recursive "$c0" -- "$c1" "$c6" 418' 419 420test_expect_success 'merge-recursive d/f conflict result' ' 421 422 git ls-files -s >actual && 423 ( 424 echo "100644 $o1 0 a" && 425 echo "100644 $o0 0 b" && 426 echo "100644 $o0 0 c" && 427 echo "100644 $o6 3 d" && 428 echo "100644 $o0 1 d/e" && 429 echo "100644 $o1 2 d/e" 430 ) >expected && 431 test_cmp expected actual 432 433' 434 435test_expect_success 'merge-recursive d/f conflict' ' 436 437 rm -fr [abcd] && 438 git reset --hard && 439 git checkout -f "$c6" && 440 441 test_expect_code 1 git merge-recursive "$c0" -- "$c6" "$c1" 442' 443 444test_expect_success 'merge-recursive d/f conflict result' ' 445 446 git ls-files -s >actual && 447 ( 448 echo "100644 $o1 0 a" && 449 echo "100644 $o0 0 b" && 450 echo "100644 $o0 0 c" && 451 echo "100644 $o6 2 d" && 452 echo "100644 $o0 1 d/e" && 453 echo "100644 $o1 3 d/e" 454 ) >expected && 455 test_cmp expected actual 456 457' 458 459test_expect_success SYMLINKS 'dir in working tree with symlink ancestor does not produce d/f conflict' ' 460 git init sym && 461 ( 462 cd sym && 463 ln -s . foo && 464 mkdir bar && 465 >bar/file && 466 git add foo bar/file && 467 git commit -m "foo symlink" && 468 469 git checkout -b branch1 && 470 git commit --allow-empty -m "empty commit" && 471 472 git checkout main && 473 git rm foo && 474 mkdir foo && 475 >foo/bar && 476 git add foo/bar && 477 git commit -m "replace foo symlink with real foo dir and foo/bar file" && 478 479 git checkout branch1 && 480 481 git cherry-pick main && 482 test_path_is_dir foo && 483 test_path_is_file foo/bar 484 ) 485' 486 487test_expect_success 'reset and 3-way merge' ' 488 489 git reset --hard "$c2" && 490 git read-tree -m "$c0" "$c2" "$c1" 491 492' 493 494test_expect_success 'reset and bind merge' ' 495 496 git reset --hard main && 497 git read-tree --prefix=M/ main && 498 git ls-files -s >actual && 499 ( 500 echo "100644 $o1 0 M/a" && 501 echo "100644 $o0 0 M/b" && 502 echo "100644 $o0 0 M/c" && 503 echo "100644 $o1 0 M/d/e" && 504 echo "100644 $o1 0 a" && 505 echo "100644 $o0 0 b" && 506 echo "100644 $o0 0 c" && 507 echo "100644 $o1 0 d/e" 508 ) >expected && 509 test_cmp expected actual && 510 511 git read-tree --prefix=a1/ main && 512 git ls-files -s >actual && 513 ( 514 echo "100644 $o1 0 M/a" && 515 echo "100644 $o0 0 M/b" && 516 echo "100644 $o0 0 M/c" && 517 echo "100644 $o1 0 M/d/e" && 518 echo "100644 $o1 0 a" && 519 echo "100644 $o1 0 a1/a" && 520 echo "100644 $o0 0 a1/b" && 521 echo "100644 $o0 0 a1/c" && 522 echo "100644 $o1 0 a1/d/e" && 523 echo "100644 $o0 0 b" && 524 echo "100644 $o0 0 c" && 525 echo "100644 $o1 0 d/e" 526 ) >expected && 527 test_cmp expected actual && 528 529 git read-tree --prefix=z/ main && 530 git ls-files -s >actual && 531 ( 532 echo "100644 $o1 0 M/a" && 533 echo "100644 $o0 0 M/b" && 534 echo "100644 $o0 0 M/c" && 535 echo "100644 $o1 0 M/d/e" && 536 echo "100644 $o1 0 a" && 537 echo "100644 $o1 0 a1/a" && 538 echo "100644 $o0 0 a1/b" && 539 echo "100644 $o0 0 a1/c" && 540 echo "100644 $o1 0 a1/d/e" && 541 echo "100644 $o0 0 b" && 542 echo "100644 $o0 0 c" && 543 echo "100644 $o1 0 d/e" && 544 echo "100644 $o1 0 z/a" && 545 echo "100644 $o0 0 z/b" && 546 echo "100644 $o0 0 z/c" && 547 echo "100644 $o1 0 z/d/e" 548 ) >expected && 549 test_cmp expected actual 550 551' 552 553test_expect_success 'merge-recursive w/ empty work tree - ours has rename' ' 554 ( 555 GIT_WORK_TREE="$PWD/ours-has-rename-work" && 556 export GIT_WORK_TREE && 557 GIT_INDEX_FILE="$PWD/ours-has-rename-index" && 558 export GIT_INDEX_FILE && 559 mkdir "$GIT_WORK_TREE" && 560 git read-tree -i -m $c7 2>actual-err && 561 test_must_be_empty actual-err && 562 git update-index --ignore-missing --refresh 2>actual-err && 563 test_must_be_empty actual-err && 564 git merge-recursive $c0 -- $c7 $c3 2>actual-err && 565 test_must_be_empty actual-err && 566 git ls-files -s >actual-files 2>actual-err && 567 test_must_be_empty actual-err 568 ) && 569 cat >expected-files <<-EOF && 570 100644 $o3 0 b/c 571 100644 $o0 0 c 572 100644 $o0 0 d/e 573 100644 $o0 0 e 574 EOF 575 test_cmp expected-files actual-files 576' 577 578test_expect_success 'merge-recursive w/ empty work tree - theirs has rename' ' 579 ( 580 GIT_WORK_TREE="$PWD/theirs-has-rename-work" && 581 export GIT_WORK_TREE && 582 GIT_INDEX_FILE="$PWD/theirs-has-rename-index" && 583 export GIT_INDEX_FILE && 584 mkdir "$GIT_WORK_TREE" && 585 git read-tree -i -m $c3 2>actual-err && 586 test_must_be_empty actual-err && 587 git update-index --ignore-missing --refresh 2>actual-err && 588 test_must_be_empty actual-err && 589 git merge-recursive $c0 -- $c3 $c7 2>actual-err && 590 test_must_be_empty actual-err && 591 git ls-files -s >actual-files 2>actual-err && 592 test_must_be_empty actual-err 593 ) && 594 cat >expected-files <<-EOF && 595 100644 $o3 0 b/c 596 100644 $o0 0 c 597 100644 $o0 0 d/e 598 100644 $o0 0 e 599 EOF 600 test_cmp expected-files actual-files 601' 602 603test_expect_success 'merge removes empty directories' ' 604 605 git reset --hard main && 606 git checkout -b rm && 607 git rm d/e && 608 git commit -mremoved-d/e && 609 git checkout main && 610 git merge -s recursive rm && 611 test_path_is_missing d 612' 613 614test_expect_success 'merge-recursive simple w/submodule' ' 615 616 git checkout submod && 617 git merge remove 618' 619 620test_expect_success 'merge-recursive simple w/submodule result' ' 621 622 git ls-files -s >actual && 623 ( 624 echo "100644 $o5 0 a" && 625 echo "100644 $o0 0 c" && 626 echo "160000 $c1 0 d" 627 ) >expected && 628 test_cmp expected actual 629' 630 631test_expect_success 'merge-recursive copy vs. rename' ' 632 git checkout -f copy && 633 git merge rename && 634 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 635 ( 636 echo "100644 blob $o0 b" && 637 echo "100644 blob $o0 c" && 638 echo "100644 blob $o0 d/e" && 639 echo "100644 blob $o0 e" && 640 echo "100644 $o0 0 b" && 641 echo "100644 $o0 0 c" && 642 echo "100644 $o0 0 d/e" && 643 echo "100644 $o0 0 e" 644 ) >expected && 645 test_cmp expected actual 646' 647 648test_expect_merge_algorithm failure success 'merge-recursive rename vs. rename/symlink' ' 649 650 git checkout -f rename && 651 git merge rename-ln && 652 ( git ls-tree -r HEAD && git ls-files -s ) >actual && 653 ( 654 echo "120000 blob $oln a" && 655 echo "100644 blob $o0 b" && 656 echo "100644 blob $o0 c" && 657 echo "100644 blob $o0 d/e" && 658 echo "100644 blob $o0 e" && 659 echo "120000 $oln 0 a" && 660 echo "100644 $o0 0 b" && 661 echo "100644 $o0 0 c" && 662 echo "100644 $o0 0 d/e" && 663 echo "100644 $o0 0 e" 664 ) >expected && 665 test_cmp expected actual 666' 667 668test_expect_success 'merging with triple rename across D/F conflict' ' 669 git reset --hard HEAD && 670 git checkout -b topic && 671 git rm -rf . && 672 673 echo "just a file" >sub1 && 674 mkdir -p sub2 && 675 echo content1 >sub2/file1 && 676 echo content2 >sub2/file2 && 677 echo content3 >sub2/file3 && 678 mkdir simple && 679 echo base >simple/bar && 680 git add -A && 681 test_tick && 682 git commit -m base && 683 684 git checkout -b other && 685 echo more >>simple/bar && 686 test_tick && 687 git commit -a -m changesimplefile && 688 689 git checkout topic && 690 git rm sub1 && 691 git mv sub2 sub1 && 692 test_tick && 693 git commit -m changefiletodir && 694 695 test_tick && 696 git merge other 697' 698 699test_expect_success 'merge-recursive remembers the names of all base trees' ' 700 git reset --hard HEAD && 701 702 # make the index match $c1 so that merge-recursive below does not 703 # fail early 704 git diff --binary HEAD $c1 -- | git apply --cached && 705 706 # more trees than static slots used by oid_to_hex() 707 for commit in $c0 $c2 $c4 $c5 $c6 $c7 708 do 709 git rev-parse "$commit^{tree}" 710 done >trees && 711 712 # ignore the return code; it only fails because the input is weird... 713 test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out && 714 715 # ...but make sure it fails in the expected way 716 test_i18ngrep CONFLICT.*rename/rename out && 717 718 # merge-recursive prints in reverse order, but we do not care 719 sort <trees >expect && 720 sed -n "s/^virtual //p" out | sort >actual && 721 test_cmp expect actual && 722 723 git clean -fd 724' 725 726test_expect_success 'merge-recursive internal merge resolves to the sameness' ' 727 git reset --hard HEAD && 728 729 # We are going to create a history leading to two criss-cross 730 # branches A and B. The common ancestor at the bottom, O0, 731 # has two child commits O1 and O2, both of which will be merge 732 # base between A and B, like so: 733 # 734 # O1---A 735 # / \ / 736 # O0 . 737 # \ / \ 738 # O2---B 739 # 740 # The recently added "check to see if the index is different from 741 # the tree into which something else is getting merged" check must 742 # NOT kick in when an inner merge between O1 and O2 is made. Both 743 # O1 and O2 happen to have the same tree as O0 in this test to 744 # trigger the bug---whether the inner merge is made by merging O2 745 # into O1 or O1 into O2, their common ancestor O0 and the branch 746 # being merged have the same tree. We should not trigger the "is 747 # the index dirty?" check in this case. 748 749 echo "zero" >file && 750 git add file && 751 test_tick && 752 git commit -m "O0" && 753 O0=$(git rev-parse HEAD) && 754 755 test_tick && 756 git commit --allow-empty -m "O1" && 757 O1=$(git rev-parse HEAD) && 758 759 git reset --hard $O0 && 760 test_tick && 761 git commit --allow-empty -m "O2" && 762 O2=$(git rev-parse HEAD) && 763 764 test_tick && 765 git merge -s ours $O1 && 766 B=$(git rev-parse HEAD) && 767 768 git reset --hard $O1 && 769 test_tick && 770 git merge -s ours $O2 && 771 A=$(git rev-parse HEAD) && 772 773 git merge $B 774' 775 776test_done 777