3 test_description
="merge cases"
5 # The setup for all of them, pictorially, is:
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.
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.)
26 .
"$TEST_DIRECTORY"/lib-merge.sh
29 ###########################################################################
30 # SECTION 1: Cases involving no renames (one side has subset of changes of
32 ###########################################################################
34 # Testcase 1a, Changes on A, subset of changes on B
45 test_write_lines
1 2 3 4 5 6 7 8 9 10 >b
&&
55 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b
&&
61 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 >b
&&
68 test_expect_success
'1a-L: Modify(A)/Modify(B), change on B subset of A' '
75 test-tool chmtime --get -3600 b >old-mtime &&
77 GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
79 test_must_be_empty err &&
81 # Make sure b was NOT updated
82 test-tool chmtime --get b >new-mtime &&
83 test_cmp old-mtime new-mtime &&
85 git ls-files -s >index_files &&
86 test_line_count = 1 index_files &&
88 git rev-parse >actual HEAD:b &&
89 git rev-parse >expect A:b &&
90 test_cmp expect actual &&
92 git hash-object b >actual &&
93 git rev-parse A:b >expect &&
94 test_cmp expect actual
98 test_expect_success
'1a-R: Modify(A)/Modify(B), change on B subset of A' '
105 test-tool chmtime --get -3600 b >old-mtime &&
106 GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
108 # Make sure b WAS updated
109 test-tool chmtime --get b >new-mtime &&
110 test $(cat old-mtime) -lt $(cat new-mtime) &&
112 test_must_be_empty err &&
114 git ls-files -s >index_files &&
115 test_line_count = 1 index_files &&
117 git rev-parse >actual HEAD:b &&
118 git rev-parse >expect A:b &&
119 test_cmp expect actual &&
121 git hash-object b >actual &&
122 git rev-parse A:b >expect &&
123 test_cmp expect actual
128 ###########################################################################
129 # SECTION 2: Cases involving basic renames
130 ###########################################################################
132 # Testcase 2a, Changes on A, rename on B
165 test_expect_success
'2a-L: Modify/rename, merge into modify side' '
172 test_path_is_missing c &&
173 GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
175 test_path_is_file c &&
177 git ls-files -s >index_files &&
178 test_line_count = 1 index_files &&
180 git rev-parse >actual HEAD:c &&
181 git rev-parse >expect A:b &&
182 test_cmp expect actual &&
184 git hash-object c >actual &&
185 git rev-parse A:b >expect &&
186 test_cmp expect actual &&
188 test_must_fail git rev-parse HEAD:b &&
189 test_path_is_missing b
193 test_expect_success
'2a-R: Modify/rename, merge into rename side' '
200 test-tool chmtime --get -3600 c >old-mtime &&
201 GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
203 # Make sure c WAS updated
204 test-tool chmtime --get c >new-mtime &&
205 test $(cat old-mtime) -lt $(cat new-mtime) &&
207 test_must_be_empty err &&
209 git ls-files -s >index_files &&
210 test_line_count = 1 index_files &&
212 git rev-parse >actual HEAD:c &&
213 git rev-parse >expect A:b &&
214 test_cmp expect actual &&
216 git hash-object c >actual &&
217 git rev-parse A:b >expect &&
218 test_cmp expect actual &&
220 test_must_fail git rev-parse HEAD:b &&
221 test_path_is_missing b
225 # Testcase 2b, Changed and renamed on A, subset of changes on B
236 test_write_lines
1 2 3 4 5 6 7 8 9 10 >b
&&
246 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b
&&
253 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 >b
&&
260 test_expect_success
'2b-L: Rename+Mod(A)/Mod(B), B mods subset of A' '
267 test-tool chmtime --get -3600 c >old-mtime &&
268 GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
270 test_must_be_empty err &&
272 # Make sure c WAS updated
273 test-tool chmtime --get c >new-mtime &&
274 test_cmp old-mtime new-mtime &&
276 git ls-files -s >index_files &&
277 test_line_count = 1 index_files &&
279 git rev-parse >actual HEAD:c &&
280 git rev-parse >expect A:c &&
281 test_cmp expect actual &&
283 git hash-object c >actual &&
284 git rev-parse A:c >expect &&
285 test_cmp expect actual &&
287 test_must_fail git rev-parse HEAD:b &&
288 test_path_is_missing b
292 test_expect_success
'2b-R: Rename+Mod(A)/Mod(B), B mods subset of A' '
299 test_path_is_missing c &&
300 GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
302 # Make sure c now present (and thus was updated)
303 test_path_is_file c &&
305 test_must_be_empty err &&
307 git ls-files -s >index_files &&
308 test_line_count = 1 index_files &&
310 git rev-parse >actual HEAD:c &&
311 git rev-parse >expect A:c &&
312 test_cmp expect actual &&
314 git hash-object c >actual &&
315 git rev-parse A:c >expect &&
316 test_cmp expect actual &&
318 test_must_fail git rev-parse HEAD:b &&
319 test_path_is_missing b
323 # Testcase 2c, Changes on A, rename on B
327 # Expected: rename/add conflict c_2 vs c_3
329 # NOTE: Since A modified b_1->b_2, and B renamed b_1->c_1, the threeway
330 # merge of those files should result in c_2. We then should have a
331 # rename/add conflict between c_2 and c_3. However, if we note in
332 # merge_content() that A had the right contents (b_2 has same
333 # contents as c_2, just at a different name), and that A had the
334 # right path present (c_3 existed) and thus decides that it can
335 # skip the update, then we're in trouble. This test verifies we do
336 # not make that particular mistake.
366 test_expect_success
'2c: Modify b & add c VS rename b->c' '
373 test-tool chmtime --get -3600 c >old-mtime &&
374 GIT_MERGE_VERBOSITY=3 &&
375 export GIT_MERGE_VERBOSITY &&
376 test_must_fail git merge -s recursive B^0 >out 2>err &&
378 test_i18ngrep "CONFLICT (.*/add):" out &&
379 test_must_be_empty err &&
381 git ls-files -s >index_files &&
382 test_line_count = 2 index_files &&
384 # Ensure b was removed
385 test_path_is_missing b &&
387 # Make sure c WAS updated...
388 test-tool chmtime --get c >new-mtime &&
389 test $(cat old-mtime) -lt $(cat new-mtime) &&
391 # ...and has correct index entries and working tree contents
392 git rev-parse >actual :2:c :3:c &&
393 git rev-parse >expect A:c A:b &&
394 test_cmp expect actual &&
396 git cat-file -p A:b >>merge-me &&
397 git cat-file -p A:c >>merged &&
399 test_must_fail git merge-file \
403 merged empty merge-me &&
409 ###########################################################################
410 # SECTION 3: Cases involving directory renames
413 # Directory renames only apply when one side renames a directory, and the
414 # other side adds or renames a path into that directory. Applying the
415 # directory rename to that new path creates a new pathname that didn't
416 # exist on either side of history. Thus, it is impossible for the
417 # merge contents to already be at the right path, so all of these checks
418 # exist just to make sure that updates are not skipped.
419 ###########################################################################
421 # Testcase 3a, Change + rename into dir foo on A, dir rename foo->bar on B
422 # Commit O: bq_1, foo/whatever
423 # Commit A: foo/{bq_2, whatever}
424 # Commit B: bq_1, bar/whatever
425 # Expected: bar/{bq_2, whatever}
434 test_write_lines a b c d e f g h i j k
>foo
/whatever
&&
435 git add bq foo
/whatever
&&
457 test_expect_success
'3a-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
464 test_path_is_missing bar/bq &&
465 GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
467 test_must_be_empty err &&
469 test_path_is_file bar/bq &&
471 git ls-files -s >index_files &&
472 test_line_count = 2 index_files &&
474 git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
475 git rev-parse >expect A:foo/bq A:foo/whatever &&
476 test_cmp expect actual &&
478 git hash-object bar/bq bar/whatever >actual &&
479 git rev-parse A:foo/bq A:foo/whatever >expect &&
480 test_cmp expect actual &&
482 test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
483 test_path_is_missing bq &&
484 test_path_is_missing foo/bq &&
485 test_path_is_missing foo/whatever
489 test_expect_success
'3a-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
496 test_path_is_missing bar/bq &&
497 GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
499 test_must_be_empty err &&
501 test_path_is_file bar/bq &&
503 git ls-files -s >index_files &&
504 test_line_count = 2 index_files &&
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 &&
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 &&
514 test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
515 test_path_is_missing bq &&
516 test_path_is_missing foo/bq &&
517 test_path_is_missing foo/whatever
521 # Testcase 3b, rename into dir foo on A, dir rename foo->bar + change on B
522 # Commit O: bq_1, foo/whatever
523 # Commit A: foo/{bq_1, whatever}
524 # Commit B: bq_2, bar/whatever
525 # Expected: bar/{bq_2, whatever}
534 test_write_lines a b c d e f g h i j k
>foo
/whatever
&&
535 git add bq foo
/whatever
&&
557 test_expect_success
'3b-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
564 test_path_is_missing bar/bq &&
565 GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
567 test_must_be_empty err &&
569 test_path_is_file bar/bq &&
571 git ls-files -s >index_files &&
572 test_line_count = 2 index_files &&
574 git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
575 git rev-parse >expect B:bq A:foo/whatever &&
576 test_cmp expect actual &&
578 git hash-object bar/bq bar/whatever >actual &&
579 git rev-parse B:bq A:foo/whatever >expect &&
580 test_cmp expect actual &&
582 test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
583 test_path_is_missing bq &&
584 test_path_is_missing foo/bq &&
585 test_path_is_missing foo/whatever
589 test_expect_success
'3b-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
596 test_path_is_missing bar/bq &&
597 GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
599 test_must_be_empty err &&
601 test_path_is_file bar/bq &&
603 git ls-files -s >index_files &&
604 test_line_count = 2 index_files &&
606 git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
607 git rev-parse >expect B:bq A:foo/whatever &&
608 test_cmp expect actual &&
610 git hash-object bar/bq bar/whatever >actual &&
611 git rev-parse B:bq A:foo/whatever >expect &&
612 test_cmp expect actual &&
614 test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
615 test_path_is_missing bq &&
616 test_path_is_missing foo/bq &&
617 test_path_is_missing foo/whatever
621 ###########################################################################
622 # SECTION 4: Cases involving dirty changes
623 ###########################################################################
625 # Testcase 4a, Changed on A, subset of changes on B, locally modified
630 # Expected: b_2 for merge, b_4 in working copy
637 test_write_lines
1 2 3 4 5 6 7 8 9 10 >b
&&
647 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b
&&
653 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 >b
&&
660 # NOTE: For as long as we continue using unpack_trees() without index_only
661 # set to true, it will error out on a case like this claiming that the locally
662 # modified file would be overwritten by the merge. Getting this testcase
663 # correct requires doing the merge in-memory first, then realizing that no
664 # updates to the file are necessary, and thus that we can just leave the path
666 test_expect_merge_algorithm failure success
'4a: Change on A, change on B subset of A, dirty mods present' '
672 echo "File rewritten" >b &&
674 test-tool chmtime --get -3600 b >old-mtime &&
676 GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
678 test_must_be_empty err &&
680 # Make sure b was NOT updated
681 test-tool chmtime --get b >new-mtime &&
682 test_cmp old-mtime new-mtime &&
684 git ls-files -s >index_files &&
685 test_line_count = 1 index_files &&
687 git rev-parse >actual :0:b &&
688 git rev-parse >expect A:b &&
689 test_cmp expect actual &&
691 git hash-object b >actual &&
692 echo "File rewritten" | git hash-object --stdin >expect &&
693 test_cmp expect actual
697 # Testcase 4b, Changed+renamed on A, subset of changes on B, locally modified
709 test_write_lines
1 2 3 4 5 6 7 8 9 10 >b
&&
719 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b
&&
726 test_write_lines
1 2 3 4 5 5.5 6 7 8 9 10 >b
&&
733 test_expect_success
'4b: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mods present' '
739 echo "File rewritten" >c &&
741 test-tool chmtime --get -3600 c >old-mtime &&
743 GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
745 test_must_be_empty err &&
747 # Make sure c was NOT updated
748 test-tool chmtime --get c >new-mtime &&
749 test_cmp old-mtime new-mtime &&
751 git ls-files -s >index_files &&
752 test_line_count = 1 index_files &&
754 git rev-parse >actual :0:c &&
755 git rev-parse >expect A:c &&
756 test_cmp expect actual &&
758 git hash-object c >actual &&
759 echo "File rewritten" | git hash-object --stdin >expect &&
760 test_cmp expect actual &&
762 test_must_fail git rev-parse HEAD:b &&
763 test_path_is_missing b