bec0192c3b71085805ee5c9aa5f92ffd3ee8fbff
1#!/bin/sh
2
3test_description="recursive merge corner cases w/ renames but not criss-crosses"
4# t6036 has corner cases that involve both criss-cross merges and renames
5
6. ./test-lib.sh
7
8test_expect_success 'setup rename/delete + untracked file' '
9 test_create_repo rename-delete-untracked &&
10 (
11 cd rename-delete-untracked &&
12
13 echo "A pretty inscription" >ring &&
14 git add ring &&
15 test_tick &&
16 git commit -m beginning &&
17
18 git branch people &&
19 git checkout -b rename-the-ring &&
20 git mv ring one-ring-to-rule-them-all &&
21 test_tick &&
22 git commit -m fullname &&
23
24 git checkout people &&
25 git rm ring &&
26 echo gollum >owner &&
27 git add owner &&
28 test_tick &&
29 git commit -m track-people-instead-of-objects &&
30 echo "Myyy PRECIOUSSS" >ring
31 )
32'
33
34test_expect_success "Does git preserve Gollum's precious artifact?" '
35 (
36 cd rename-delete-untracked &&
37
38 test_must_fail git merge -s recursive rename-the-ring &&
39
40 # Make sure git did not delete an untracked file
41 test -f ring
42 )
43'
44
45# Testcase setup for rename/modify/add-source:
46# Commit A: new file: a
47# Commit B: modify a slightly
48# Commit C: rename a->b, add completely different a
49#
50# We should be able to merge B & C cleanly
51
52test_expect_success 'setup rename/modify/add-source conflict' '
53 test_create_repo rename-modify-add-source &&
54 (
55 cd rename-modify-add-source &&
56
57 printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
58 git add a &&
59 git commit -m A &&
60 git tag A &&
61
62 git checkout -b B A &&
63 echo 8 >>a &&
64 git add a &&
65 git commit -m B &&
66
67 git checkout -b C A &&
68 git mv a b &&
69 echo something completely different >a &&
70 git add a &&
71 git commit -m C
72 )
73'
74
75test_expect_failure 'rename/modify/add-source conflict resolvable' '
76 (
77 cd rename-modify-add-source &&
78
79 git checkout B^0 &&
80
81 git merge -s recursive C^0 &&
82
83 test $(git rev-parse B:a) = $(git rev-parse b) &&
84 test $(git rev-parse C:a) = $(git rev-parse a)
85 )
86'
87
88test_expect_success 'setup resolvable conflict missed if rename missed' '
89 test_create_repo break-detection-1 &&
90 (
91 cd break-detection-1 &&
92
93 printf "1\n2\n3\n4\n5\n" >a &&
94 echo foo >b &&
95 git add a b &&
96 git commit -m A &&
97 git tag A &&
98
99 git checkout -b B A &&
100 git mv a c &&
101 echo "Completely different content" >a &&
102 git add a &&
103 git commit -m B &&
104
105 git checkout -b C A &&
106 echo 6 >>a &&
107 git add a &&
108 git commit -m C
109 )
110'
111
112test_expect_failure 'conflict caused if rename not detected' '
113 (
114 cd break-detection-1 &&
115
116 git checkout -q C^0 &&
117 git merge -s recursive B^0 &&
118
119 test 3 -eq $(git ls-files -s | wc -l) &&
120 test 0 -eq $(git ls-files -u | wc -l) &&
121 test 0 -eq $(git ls-files -o | wc -l) &&
122
123 test_line_count = 6 c &&
124 test $(git rev-parse HEAD:a) = $(git rev-parse B:a) &&
125 test $(git rev-parse HEAD:b) = $(git rev-parse A:b)
126 )
127'
128
129test_expect_success 'setup conflict resolved wrong if rename missed' '
130 test_create_repo break-detection-2 &&
131 (
132 cd break-detection-2 &&
133
134 printf "1\n2\n3\n4\n5\n" >a &&
135 echo foo >b &&
136 git add a b &&
137 git commit -m A &&
138 git tag A &&
139
140 git checkout -b D A &&
141 echo 7 >>a &&
142 git add a &&
143 git mv a c &&
144 echo "Completely different content" >a &&
145 git add a &&
146 git commit -m D &&
147
148 git checkout -b E A &&
149 git rm a &&
150 echo "Completely different content" >>a &&
151 git add a &&
152 git commit -m E
153 )
154'
155
156test_expect_failure 'missed conflict if rename not detected' '
157 (
158 cd break-detection-2 &&
159
160 git checkout -q E^0 &&
161 test_must_fail git merge -s recursive D^0
162 )
163'
164
165# Tests for undetected rename/add-source causing a file to erroneously be
166# deleted (and for mishandled rename/rename(1to1) causing the same issue).
167#
168# This test uses a rename/rename(1to1)+add-source conflict (1to1 means the
169# same file is renamed on both sides to the same thing; it should trigger
170# the 1to2 logic, which it would do if the add-source didn't cause issues
171# for git's rename detection):
172# Commit A: new file: a
173# Commit B: rename a->b
174# Commit C: rename a->b, add unrelated a
175
176test_expect_success 'setup undetected rename/add-source causes data loss' '
177 test_create_repo break-detection-3 &&
178 (
179 cd break-detection-3 &&
180
181 printf "1\n2\n3\n4\n5\n" >a &&
182 git add a &&
183 git commit -m A &&
184 git tag A &&
185
186 git checkout -b B A &&
187 git mv a b &&
188 git commit -m B &&
189
190 git checkout -b C A &&
191 git mv a b &&
192 echo foobar >a &&
193 git add a &&
194 git commit -m C
195 )
196'
197
198test_expect_failure 'detect rename/add-source and preserve all data' '
199 (
200 cd break-detection-3 &&
201
202 git checkout B^0 &&
203
204 git merge -s recursive C^0 &&
205
206 test 2 -eq $(git ls-files -s | wc -l) &&
207 test 2 -eq $(git ls-files -u | wc -l) &&
208 test 0 -eq $(git ls-files -o | wc -l) &&
209
210 test -f a &&
211 test -f b &&
212
213 test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
214 test $(git rev-parse HEAD:a) = $(git rev-parse C:a)
215 )
216'
217
218test_expect_failure 'detect rename/add-source and preserve all data, merge other way' '
219 (
220 cd break-detection-3 &&
221
222 git checkout C^0 &&
223
224 git merge -s recursive B^0 &&
225
226 test 2 -eq $(git ls-files -s | wc -l) &&
227 test 2 -eq $(git ls-files -u | wc -l) &&
228 test 0 -eq $(git ls-files -o | wc -l) &&
229
230 test -f a &&
231 test -f b &&
232
233 test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
234 test $(git rev-parse HEAD:a) = $(git rev-parse C:a)
235 )
236'
237
238test_expect_success 'setup content merge + rename/directory conflict' '
239 test_create_repo rename-directory-1 &&
240 (
241 cd rename-directory-1 &&
242
243 printf "1\n2\n3\n4\n5\n6\n" >file &&
244 git add file &&
245 test_tick &&
246 git commit -m base &&
247 git tag base &&
248
249 git checkout -b right &&
250 echo 7 >>file &&
251 mkdir newfile &&
252 echo junk >newfile/realfile &&
253 git add file newfile/realfile &&
254 test_tick &&
255 git commit -m right &&
256
257 git checkout -b left-conflict base &&
258 echo 8 >>file &&
259 git add file &&
260 git mv file newfile &&
261 test_tick &&
262 git commit -m left &&
263
264 git checkout -b left-clean base &&
265 echo 0 >newfile &&
266 cat file >>newfile &&
267 git add newfile &&
268 git rm file &&
269 test_tick &&
270 git commit -m left
271 )
272'
273
274test_expect_success 'rename/directory conflict + clean content merge' '
275 (
276 cd rename-directory-1 &&
277
278 git checkout left-clean^0 &&
279
280 test_must_fail git merge -s recursive right^0 &&
281
282 test 2 -eq $(git ls-files -s | wc -l) &&
283 test 1 -eq $(git ls-files -u | wc -l) &&
284 test 1 -eq $(git ls-files -o | wc -l) &&
285
286 echo 0 >expect &&
287 git cat-file -p base:file >>expect &&
288 echo 7 >>expect &&
289 test_cmp expect newfile~HEAD &&
290
291 test $(git rev-parse :2:newfile) = $(git hash-object expect) &&
292
293 test -f newfile/realfile &&
294 test -f newfile~HEAD
295 )
296'
297
298test_expect_success 'rename/directory conflict + content merge conflict' '
299 (
300 cd rename-directory-1 &&
301
302 git reset --hard &&
303 git reset --hard &&
304 git clean -fdqx &&
305
306 git checkout left-conflict^0 &&
307
308 test_must_fail git merge -s recursive right^0 &&
309
310 test 4 -eq $(git ls-files -s | wc -l) &&
311 test 3 -eq $(git ls-files -u | wc -l) &&
312 test 1 -eq $(git ls-files -o | wc -l) &&
313
314 git cat-file -p left-conflict:newfile >left &&
315 git cat-file -p base:file >base &&
316 git cat-file -p right:file >right &&
317 test_must_fail git merge-file \
318 -L "HEAD:newfile" \
319 -L "" \
320 -L "right^0:file" \
321 left base right &&
322 test_cmp left newfile~HEAD &&
323
324 test $(git rev-parse :1:newfile) = $(git rev-parse base:file) &&
325 test $(git rev-parse :2:newfile) = $(git rev-parse left-conflict:newfile) &&
326 test $(git rev-parse :3:newfile) = $(git rev-parse right:file) &&
327
328 test -f newfile/realfile &&
329 test -f newfile~HEAD
330 )
331'
332
333test_expect_success 'setup content merge + rename/directory conflict w/ disappearing dir' '
334 test_create_repo rename-directory-2 &&
335 (
336 cd rename-directory-2 &&
337
338 mkdir sub &&
339 printf "1\n2\n3\n4\n5\n6\n" >sub/file &&
340 git add sub/file &&
341 test_tick &&
342 git commit -m base &&
343 git tag base &&
344
345 git checkout -b right &&
346 echo 7 >>sub/file &&
347 git add sub/file &&
348 test_tick &&
349 git commit -m right &&
350
351 git checkout -b left base &&
352 echo 0 >newfile &&
353 cat sub/file >>newfile &&
354 git rm sub/file &&
355 mv newfile sub &&
356 git add sub &&
357 test_tick &&
358 git commit -m left
359 )
360'
361
362test_expect_success 'disappearing dir in rename/directory conflict handled' '
363 (
364 cd rename-directory-2 &&
365
366 git checkout left^0 &&
367
368 git merge -s recursive right^0 &&
369
370 test 1 -eq $(git ls-files -s | wc -l) &&
371 test 0 -eq $(git ls-files -u | wc -l) &&
372 test 0 -eq $(git ls-files -o | wc -l) &&
373
374 echo 0 >expect &&
375 git cat-file -p base:sub/file >>expect &&
376 echo 7 >>expect &&
377 test_cmp expect sub &&
378
379 test -f sub
380 )
381'
382
383# Test for all kinds of things that can go wrong with rename/rename (2to1):
384# Commit A: new files: a & b
385# Commit B: rename a->c, modify b
386# Commit C: rename b->c, modify a
387#
388# Merging of B & C should NOT be clean. Questions:
389# * Both a & b should be removed by the merge; are they?
390# * The two c's should contain modifications to a & b; do they?
391# * The index should contain two files, both for c; does it?
392# * The working copy should have two files, both of form c~<unique>; does it?
393# * Nothing else should be present. Is anything?
394
395test_expect_success 'setup rename/rename (2to1) + modify/modify' '
396 test_create_repo rename-rename-2to1 &&
397 (
398 cd rename-rename-2to1 &&
399
400 printf "1\n2\n3\n4\n5\n" >a &&
401 printf "5\n4\n3\n2\n1\n" >b &&
402 git add a b &&
403 git commit -m A &&
404 git tag A &&
405
406 git checkout -b B A &&
407 git mv a c &&
408 echo 0 >>b &&
409 git add b &&
410 git commit -m B &&
411
412 git checkout -b C A &&
413 git mv b c &&
414 echo 6 >>a &&
415 git add a &&
416 git commit -m C
417 )
418'
419
420test_expect_success 'handle rename/rename (2to1) conflict correctly' '
421 (
422 cd rename-rename-2to1 &&
423
424 git checkout B^0 &&
425
426 test_must_fail git merge -s recursive C^0 >out &&
427 test_i18ngrep "CONFLICT (rename/rename)" out &&
428
429 test 2 -eq $(git ls-files -s | wc -l) &&
430 test 2 -eq $(git ls-files -u | wc -l) &&
431 test 2 -eq $(git ls-files -u c | wc -l) &&
432 test 3 -eq $(git ls-files -o | wc -l) &&
433
434 test ! -f a &&
435 test ! -f b &&
436 test -f c~HEAD &&
437 test -f c~C^0 &&
438
439 test $(git hash-object c~HEAD) = $(git rev-parse C:a) &&
440 test $(git hash-object c~C^0) = $(git rev-parse B:b)
441 )
442'
443
444# Testcase setup for simple rename/rename (1to2) conflict:
445# Commit A: new file: a
446# Commit B: rename a->b
447# Commit C: rename a->c
448test_expect_success 'setup simple rename/rename (1to2) conflict' '
449 test_create_repo rename-rename-1to2 &&
450 (
451 cd rename-rename-1to2 &&
452
453 echo stuff >a &&
454 git add a &&
455 test_tick &&
456 git commit -m A &&
457 git tag A &&
458
459 git checkout -b B A &&
460 git mv a b &&
461 test_tick &&
462 git commit -m B &&
463
464 git checkout -b C A &&
465 git mv a c &&
466 test_tick &&
467 git commit -m C
468 )
469'
470
471test_expect_success 'merge has correct working tree contents' '
472 (
473 cd rename-rename-1to2 &&
474
475 git checkout C^0 &&
476
477 test_must_fail git merge -s recursive B^0 &&
478
479 test 3 -eq $(git ls-files -s | wc -l) &&
480 test 3 -eq $(git ls-files -u | wc -l) &&
481 test 0 -eq $(git ls-files -o | wc -l) &&
482
483 test $(git rev-parse :1:a) = $(git rev-parse A:a) &&
484 test $(git rev-parse :3:b) = $(git rev-parse A:a) &&
485 test $(git rev-parse :2:c) = $(git rev-parse A:a) &&
486
487 test ! -f a &&
488 test $(git hash-object b) = $(git rev-parse A:a) &&
489 test $(git hash-object c) = $(git rev-parse A:a)
490 )
491'
492
493# Testcase setup for rename/rename(1to2)/add-source conflict:
494# Commit A: new file: a
495# Commit B: rename a->b
496# Commit C: rename a->c, add completely different a
497#
498# Merging of B & C should NOT be clean; there's a rename/rename conflict
499
500test_expect_success 'setup rename/rename(1to2)/add-source conflict' '
501 test_create_repo rename-rename-1to2-add-source-1 &&
502 (
503 cd rename-rename-1to2-add-source-1 &&
504
505 printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
506 git add a &&
507 git commit -m A &&
508 git tag A &&
509
510 git checkout -b B A &&
511 git mv a b &&
512 git commit -m B &&
513
514 git checkout -b C A &&
515 git mv a c &&
516 echo something completely different >a &&
517 git add a &&
518 git commit -m C
519 )
520'
521
522test_expect_failure 'detect conflict with rename/rename(1to2)/add-source merge' '
523 (
524 cd rename-rename-1to2-add-source-1 &&
525
526 git checkout B^0 &&
527
528 test_must_fail git merge -s recursive C^0 &&
529
530 test 4 -eq $(git ls-files -s | wc -l) &&
531 test 0 -eq $(git ls-files -o | wc -l) &&
532
533 test $(git rev-parse 3:a) = $(git rev-parse C:a) &&
534 test $(git rev-parse 1:a) = $(git rev-parse A:a) &&
535 test $(git rev-parse 2:b) = $(git rev-parse B:b) &&
536 test $(git rev-parse 3:c) = $(git rev-parse C:c) &&
537
538 test -f a &&
539 test -f b &&
540 test -f c
541 )
542'
543
544test_expect_success 'setup rename/rename(1to2)/add-source resolvable conflict' '
545 test_create_repo rename-rename-1to2-add-source-2 &&
546 (
547 cd rename-rename-1to2-add-source-2 &&
548
549 >a &&
550 git add a &&
551 test_tick &&
552 git commit -m base &&
553 git tag A &&
554
555 git checkout -b B A &&
556 git mv a b &&
557 test_tick &&
558 git commit -m one &&
559
560 git checkout -b C A &&
561 git mv a b &&
562 echo important-info >a &&
563 git add a &&
564 test_tick &&
565 git commit -m two
566 )
567'
568
569test_expect_failure 'rename/rename/add-source still tracks new a file' '
570 (
571 cd rename-rename-1to2-add-source-2 &&
572
573 git checkout C^0 &&
574 git merge -s recursive B^0 &&
575
576 test 2 -eq $(git ls-files -s | wc -l) &&
577 test 0 -eq $(git ls-files -o | wc -l) &&
578
579 test $(git rev-parse HEAD:a) = $(git rev-parse C:a) &&
580 test $(git rev-parse HEAD:b) = $(git rev-parse A:a)
581 )
582'
583
584test_expect_success 'setup rename/rename(1to2)/add-dest conflict' '
585 test_create_repo rename-rename-1to2-add-dest &&
586 (
587 cd rename-rename-1to2-add-dest &&
588
589 echo stuff >a &&
590 git add a &&
591 test_tick &&
592 git commit -m base &&
593 git tag A &&
594
595 git checkout -b B A &&
596 git mv a b &&
597 echo precious-data >c &&
598 git add c &&
599 test_tick &&
600 git commit -m one &&
601
602 git checkout -b C A &&
603 git mv a c &&
604 echo important-info >b &&
605 git add b &&
606 test_tick &&
607 git commit -m two
608 )
609'
610
611test_expect_success 'rename/rename/add-dest merge still knows about conflicting file versions' '
612 (
613 cd rename-rename-1to2-add-dest &&
614
615 git checkout C^0 &&
616 test_must_fail git merge -s recursive B^0 &&
617
618 test 5 -eq $(git ls-files -s | wc -l) &&
619 test 2 -eq $(git ls-files -u b | wc -l) &&
620 test 2 -eq $(git ls-files -u c | wc -l) &&
621 test 4 -eq $(git ls-files -o | wc -l) &&
622
623 test $(git rev-parse :1:a) = $(git rev-parse A:a) &&
624 test $(git rev-parse :2:b) = $(git rev-parse C:b) &&
625 test $(git rev-parse :3:b) = $(git rev-parse B:b) &&
626 test $(git rev-parse :2:c) = $(git rev-parse C:c) &&
627 test $(git rev-parse :3:c) = $(git rev-parse B:c) &&
628
629 test $(git hash-object c~HEAD) = $(git rev-parse C:c) &&
630 test $(git hash-object c~B\^0) = $(git rev-parse B:c) &&
631 test $(git hash-object b~HEAD) = $(git rev-parse C:b) &&
632 test $(git hash-object b~B\^0) = $(git rev-parse B:b) &&
633
634 test ! -f b &&
635 test ! -f c
636 )
637'
638
639test_done