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