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