Merge branch 'pb/recurse-submodules-fix'
[git] / t / t6022-merge-rename.sh
1 #!/bin/sh
2
3 test_description='Merge-recursive merging renames'
4 . ./test-lib.sh
5
6 modify () {
7         sed -e "$1" <"$2" >"$2.x" &&
8         mv "$2.x" "$2"
9 }
10
11 test_expect_success 'setup' '
12         cat >A <<-\EOF &&
13         a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
14         b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
15         c cccccccccccccccccccccccccccccccccccccccccccccccc
16         d dddddddddddddddddddddddddddddddddddddddddddddddd
17         e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
18         f ffffffffffffffffffffffffffffffffffffffffffffffff
19         g gggggggggggggggggggggggggggggggggggggggggggggggg
20         h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
21         i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
22         j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
23         k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
24         l llllllllllllllllllllllllllllllllllllllllllllllll
25         m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
26         n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
27         o oooooooooooooooooooooooooooooooooooooooooooooooo
28         EOF
29
30         cat >M <<-\EOF &&
31         A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
32         B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
33         C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
34         D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
35         E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
36         F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
37         G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
38         H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
39         I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
40         J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
41         K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
42         L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
43         M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
44         N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
45         O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
46         EOF
47
48         git add A M &&
49         git commit -m "initial has A and M" &&
50         git branch white &&
51         git branch red &&
52         git branch blue &&
53         git branch yellow &&
54         git branch change &&
55         git branch change+rename &&
56
57         sed -e "/^g /s/.*/g : master changes a line/" <A >A+ &&
58         mv A+ A &&
59         git commit -a -m "master updates A" &&
60
61         git checkout yellow &&
62         rm -f M &&
63         git commit -a -m "yellow removes M" &&
64
65         git checkout white &&
66         sed -e "/^g /s/.*/g : white changes a line/" <A >B &&
67         sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
68         rm -f A M &&
69         git update-index --add --remove A B M N &&
70         git commit -m "white renames A->B, M->N" &&
71
72         git checkout red &&
73         sed -e "/^g /s/.*/g : red changes a line/" <A >B &&
74         sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
75         rm -f A M &&
76         git update-index --add --remove A B M N &&
77         git commit -m "red renames A->B, M->N" &&
78
79         git checkout blue &&
80         sed -e "/^g /s/.*/g : blue changes a line/" <A >C &&
81         sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
82         rm -f A M &&
83         git update-index --add --remove A C M N &&
84         git commit -m "blue renames A->C, M->N" &&
85
86         git checkout change &&
87         sed -e "/^g /s/.*/g : changed line/" <A >A+ &&
88         mv A+ A &&
89         git commit -q -a -m "changed" &&
90
91         git checkout change+rename &&
92         sed -e "/^g /s/.*/g : changed line/" <A >B &&
93         rm A &&
94         git update-index --add B &&
95         git commit -q -a -m "changed and renamed" &&
96
97         git checkout master
98 '
99
100 test_expect_success 'pull renaming branch into unrenaming one' \
101 '
102         git show-branch &&
103         test_expect_code 1 git pull . white &&
104         git ls-files -s &&
105         git ls-files -u B >b.stages &&
106         test_line_count = 3 b.stages &&
107         git ls-files -s N >n.stages &&
108         test_line_count = 1 n.stages &&
109         sed -ne "/^g/{
110         p
111         q
112         }" B | grep master &&
113         git diff --exit-code white N
114 '
115
116 test_expect_success 'pull renaming branch into another renaming one' \
117 '
118         rm -f B &&
119         git reset --hard &&
120         git checkout red &&
121         test_expect_code 1 git pull . white &&
122         git ls-files -u B >b.stages &&
123         test_line_count = 3 b.stages &&
124         git ls-files -s N >n.stages &&
125         test_line_count = 1 n.stages &&
126         sed -ne "/^g/{
127         p
128         q
129         }" B | grep red &&
130         git diff --exit-code white N
131 '
132
133 test_expect_success 'pull unrenaming branch into renaming one' \
134 '
135         git reset --hard &&
136         git show-branch &&
137         test_expect_code 1 git pull . master &&
138         git ls-files -u B >b.stages &&
139         test_line_count = 3 b.stages &&
140         git ls-files -s N >n.stages &&
141         test_line_count = 1 n.stages &&
142         sed -ne "/^g/{
143         p
144         q
145         }" B | grep red &&
146         git diff --exit-code white N
147 '
148
149 test_expect_success 'pull conflicting renames' \
150 '
151         git reset --hard &&
152         git show-branch &&
153         test_expect_code 1 git pull . blue &&
154         git ls-files -u A >a.stages &&
155         test_line_count = 1 a.stages &&
156         git ls-files -u B >b.stages &&
157         test_line_count = 1 b.stages &&
158         git ls-files -u C >c.stages &&
159         test_line_count = 1 c.stages &&
160         git ls-files -s N >n.stages &&
161         test_line_count = 1 n.stages &&
162         sed -ne "/^g/{
163         p
164         q
165         }" B | grep red &&
166         git diff --exit-code white N
167 '
168
169 test_expect_success 'interference with untracked working tree file' '
170         git reset --hard &&
171         git show-branch &&
172         echo >A this file should not matter &&
173         test_expect_code 1 git pull . white &&
174         test_path_is_file A
175 '
176
177 test_expect_success 'interference with untracked working tree file' '
178         git reset --hard &&
179         git checkout white &&
180         git show-branch &&
181         rm -f A &&
182         echo >A this file should not matter &&
183         test_expect_code 1 git pull . red &&
184         test_path_is_file A
185 '
186
187 test_expect_success 'interference with untracked working tree file' '
188         git reset --hard &&
189         rm -f A M &&
190         git checkout -f master &&
191         git tag -f anchor &&
192         git show-branch &&
193         git pull . yellow &&
194         test_path_is_missing M &&
195         git reset --hard anchor
196 '
197
198 test_expect_success 'updated working tree file should prevent the merge' '
199         git reset --hard &&
200         rm -f A M &&
201         git checkout -f master &&
202         git tag -f anchor &&
203         git show-branch &&
204         echo >>M one line addition &&
205         cat M >M.saved &&
206         test_expect_code 128 git pull . yellow &&
207         test_cmp M M.saved &&
208         rm -f M.saved
209 '
210
211 test_expect_success 'updated working tree file should prevent the merge' '
212         git reset --hard &&
213         rm -f A M &&
214         git checkout -f master &&
215         git tag -f anchor &&
216         git show-branch &&
217         echo >>M one line addition &&
218         cat M >M.saved &&
219         git update-index M &&
220         test_expect_code 128 git pull . yellow &&
221         test_cmp M M.saved &&
222         rm -f M.saved
223 '
224
225 test_expect_success 'interference with untracked working tree file' '
226         git reset --hard &&
227         rm -f A M &&
228         git checkout -f yellow &&
229         git tag -f anchor &&
230         git show-branch &&
231         echo >M this file should not matter &&
232         git pull . master &&
233         test_path_is_file M &&
234         ! {
235                 git ls-files -s |
236                 grep M
237         } &&
238         git reset --hard anchor
239 '
240
241 test_expect_success 'merge of identical changes in a renamed file' '
242         rm -f A M N &&
243         git reset --hard &&
244         git checkout change+rename &&
245
246         test-tool chmtime --get -3600 B >old-mtime &&
247         GIT_MERGE_VERBOSITY=3 git merge change >out &&
248
249         test-tool chmtime --get B >new-mtime &&
250         test_cmp old-mtime new-mtime &&
251
252         git reset --hard HEAD^ &&
253         git checkout change &&
254
255         # A will be renamed to B; we check mtimes and file presence
256         test_path_is_missing B &&
257         test-tool chmtime --get -3600 A >old-mtime &&
258         GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&
259
260         test_path_is_missing A &&
261         test-tool chmtime --get B >new-mtime &&
262         test $(cat old-mtime) -lt $(cat new-mtime)
263 '
264
265 test_expect_success 'setup for rename + d/f conflicts' '
266         git reset --hard &&
267         git checkout --orphan dir-in-way &&
268         git rm -rf . &&
269         git clean -fdqx &&
270
271         mkdir sub &&
272         mkdir dir &&
273         printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >sub/file &&
274         echo foo >dir/file-in-the-way &&
275         git add -A &&
276         git commit -m "Common commit" &&
277
278         echo 11 >>sub/file &&
279         echo more >>dir/file-in-the-way &&
280         git add -u &&
281         git commit -m "Commit to merge, with dir in the way" &&
282
283         git checkout -b dir-not-in-way &&
284         git reset --soft HEAD^ &&
285         git rm -rf dir &&
286         git commit -m "Commit to merge, with dir removed" -- dir sub/file &&
287
288         git checkout -b renamed-file-has-no-conflicts dir-in-way~1 &&
289         git rm -rf dir &&
290         git rm sub/file &&
291         printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n" >dir &&
292         git add dir &&
293         git commit -m "Independent change" &&
294
295         git checkout -b renamed-file-has-conflicts dir-in-way~1 &&
296         git rm -rf dir &&
297         git mv sub/file dir &&
298         echo 12 >>dir &&
299         git add dir &&
300         git commit -m "Conflicting change"
301 '
302
303 test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way' '
304         git reset --hard &&
305         git checkout -q renamed-file-has-no-conflicts^0 &&
306
307         git merge --strategy=recursive dir-not-in-way &&
308
309         git diff --quiet &&
310         test_path_is_file dir &&
311         test_write_lines 1 2 3 4 5555 6 7 8 9 10 11 >expected &&
312         test_cmp expected dir
313 '
314
315 test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' '
316         git reset --hard &&
317         rm -rf dir~* &&
318         git checkout -q renamed-file-has-no-conflicts^0 &&
319         test_must_fail git merge --strategy=recursive dir-in-way >output &&
320
321         test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
322         test_i18ngrep "Auto-merging dir" output &&
323         test_i18ngrep "Adding as dir~HEAD instead" output &&
324
325         test 3 -eq "$(git ls-files -u | wc -l)" &&
326         test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
327
328         test_must_fail git diff --quiet &&
329         test_must_fail git diff --cached --quiet &&
330
331         test_path_is_file dir/file-in-the-way &&
332         test_path_is_file dir~HEAD &&
333         test_cmp expected dir~HEAD
334 '
335
336 test_expect_success 'Same as previous, but merged other way' '
337         git reset --hard &&
338         rm -rf dir~* &&
339         git checkout -q dir-in-way^0 &&
340         test_must_fail git merge --strategy=recursive renamed-file-has-no-conflicts >output 2>errors &&
341
342         ! grep "error: refusing to lose untracked file at" errors &&
343         test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
344         test_i18ngrep "Auto-merging dir" output &&
345         test_i18ngrep "Adding as dir~renamed-file-has-no-conflicts instead" output &&
346
347         test 3 -eq "$(git ls-files -u | wc -l)" &&
348         test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
349
350         test_must_fail git diff --quiet &&
351         test_must_fail git diff --cached --quiet &&
352
353         test_path_is_file dir/file-in-the-way &&
354         test_path_is_file dir~renamed-file-has-no-conflicts &&
355         test_cmp expected dir~renamed-file-has-no-conflicts
356 '
357
358 test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' '
359         git reset --hard &&
360         rm -rf dir~* &&
361         git checkout -q renamed-file-has-conflicts^0 &&
362         test_must_fail git merge --strategy=recursive dir-not-in-way &&
363
364         test 3 -eq "$(git ls-files -u | wc -l)" &&
365         test 3 -eq "$(git ls-files -u dir | wc -l)" &&
366
367         test_must_fail git diff --quiet &&
368         test_must_fail git diff --cached --quiet &&
369
370         test_path_is_file dir &&
371         cat >expected <<-\EOF &&
372         1
373         2
374         3
375         4
376         5
377         6
378         7
379         8
380         9
381         10
382         <<<<<<< HEAD:dir
383         12
384         =======
385         11
386         >>>>>>> dir-not-in-way:sub/file
387         EOF
388         test_cmp expected dir
389 '
390
391 test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in the way' '
392         modify s/dir-not-in-way/dir-in-way/ expected &&
393
394         git reset --hard &&
395         rm -rf dir~* &&
396         git checkout -q renamed-file-has-conflicts^0 &&
397         test_must_fail git merge --strategy=recursive dir-in-way &&
398
399         test 5 -eq "$(git ls-files -u | wc -l)" &&
400         test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
401         test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
402
403         test_must_fail git diff --quiet &&
404         test_must_fail git diff --cached --quiet &&
405
406         test_path_is_file dir/file-in-the-way &&
407         test_path_is_file dir~HEAD &&
408         test_cmp expected dir~HEAD
409 '
410
411 test_expect_success 'Same as previous, but merged other way' '
412         git reset --hard &&
413         rm -rf dir~* &&
414         git checkout -q dir-in-way^0 &&
415         test_must_fail git merge --strategy=recursive renamed-file-has-conflicts &&
416
417         test 5 -eq "$(git ls-files -u | wc -l)" &&
418         test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
419         test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
420
421         test_must_fail git diff --quiet &&
422         test_must_fail git diff --cached --quiet &&
423
424         test_path_is_file dir/file-in-the-way &&
425         test_path_is_file dir~renamed-file-has-conflicts &&
426         cat >expected <<-\EOF &&
427         1
428         2
429         3
430         4
431         5
432         6
433         7
434         8
435         9
436         10
437         <<<<<<< HEAD:sub/file
438         11
439         =======
440         12
441         >>>>>>> renamed-file-has-conflicts:dir
442         EOF
443         test_cmp expected dir~renamed-file-has-conflicts
444 '
445
446 test_expect_success 'setup both rename source and destination involved in D/F conflict' '
447         git reset --hard &&
448         git checkout --orphan rename-dest &&
449         git rm -rf . &&
450         git clean -fdqx &&
451
452         mkdir one &&
453         echo stuff >one/file &&
454         git add -A &&
455         git commit -m "Common commit" &&
456
457         git mv one/file destdir &&
458         git commit -m "Renamed to destdir" &&
459
460         git checkout -b source-conflict HEAD~1 &&
461         git rm -rf one &&
462         mkdir destdir &&
463         touch one destdir/foo &&
464         git add -A &&
465         git commit -m "Conflicts in the way"
466 '
467
468 test_expect_success 'both rename source and destination involved in D/F conflict' '
469         git reset --hard &&
470         rm -rf dir~* &&
471         git checkout -q rename-dest^0 &&
472         test_must_fail git merge --strategy=recursive source-conflict &&
473
474         test 1 -eq "$(git ls-files -u | wc -l)" &&
475
476         test_must_fail git diff --quiet &&
477
478         test_path_is_file destdir/foo &&
479         test_path_is_file one &&
480         test_path_is_file destdir~HEAD &&
481         test "stuff" = "$(cat destdir~HEAD)"
482 '
483
484 test_expect_success 'setup pair rename to parent of other (D/F conflicts)' '
485         git reset --hard &&
486         git checkout --orphan rename-two &&
487         git rm -rf . &&
488         git clean -fdqx &&
489
490         mkdir one &&
491         mkdir two &&
492         echo stuff >one/file &&
493         echo other >two/file &&
494         git add -A &&
495         git commit -m "Common commit" &&
496
497         git rm -rf one &&
498         git mv two/file one &&
499         git commit -m "Rename two/file -> one" &&
500
501         git checkout -b rename-one HEAD~1 &&
502         git rm -rf two &&
503         git mv one/file two &&
504         rm -r one &&
505         git commit -m "Rename one/file -> two"
506 '
507
508 test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' '
509         git checkout -q rename-one^0 &&
510         mkdir one &&
511         test_must_fail git merge --strategy=recursive rename-two &&
512
513         test 2 -eq "$(git ls-files -u | wc -l)" &&
514         test 1 -eq "$(git ls-files -u one | wc -l)" &&
515         test 1 -eq "$(git ls-files -u two | wc -l)" &&
516
517         test_must_fail git diff --quiet &&
518
519         test 4 -eq $(find . | grep -v .git | wc -l) &&
520
521         test_path_is_dir one &&
522         test_path_is_file one~rename-two &&
523         test_path_is_file two &&
524         test "other" = $(cat one~rename-two) &&
525         test "stuff" = $(cat two)
526 '
527
528 test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean start' '
529         git reset --hard &&
530         git clean -fdqx &&
531         test_must_fail git merge --strategy=recursive rename-two &&
532
533         test 2 -eq "$(git ls-files -u | wc -l)" &&
534         test 1 -eq "$(git ls-files -u one | wc -l)" &&
535         test 1 -eq "$(git ls-files -u two | wc -l)" &&
536
537         test_must_fail git diff --quiet &&
538
539         test 3 -eq $(find . | grep -v .git | wc -l) &&
540
541         test_path_is_file one &&
542         test_path_is_file two &&
543         test "other" = $(cat one) &&
544         test "stuff" = $(cat two)
545 '
546
547 test_expect_success 'setup rename of one file to two, with directories in the way' '
548         git reset --hard &&
549         git checkout --orphan first-rename &&
550         git rm -rf . &&
551         git clean -fdqx &&
552
553         echo stuff >original &&
554         git add -A &&
555         git commit -m "Common commit" &&
556
557         mkdir two &&
558         >two/file &&
559         git add two/file &&
560         git mv original one &&
561         git commit -m "Put two/file in the way, rename to one" &&
562
563         git checkout -b second-rename HEAD~1 &&
564         mkdir one &&
565         >one/file &&
566         git add one/file &&
567         git mv original two &&
568         git commit -m "Put one/file in the way, rename to two"
569 '
570
571 test_expect_success 'check handling of differently renamed file with D/F conflicts' '
572         git checkout -q first-rename^0 &&
573         test_must_fail git merge --strategy=recursive second-rename &&
574
575         test 5 -eq "$(git ls-files -s | wc -l)" &&
576         test 3 -eq "$(git ls-files -u | wc -l)" &&
577         test 1 -eq "$(git ls-files -u one | wc -l)" &&
578         test 1 -eq "$(git ls-files -u two | wc -l)" &&
579         test 1 -eq "$(git ls-files -u original | wc -l)" &&
580         test 2 -eq "$(git ls-files -o | wc -l)" &&
581
582         test_path_is_file one/file &&
583         test_path_is_file two/file &&
584         test_path_is_file one~HEAD &&
585         test_path_is_file two~second-rename &&
586         test_path_is_missing original
587 '
588
589 test_expect_success 'setup rename one file to two; directories moving out of the way' '
590         git reset --hard &&
591         git checkout --orphan first-rename-redo &&
592         git rm -rf . &&
593         git clean -fdqx &&
594
595         echo stuff >original &&
596         mkdir one two &&
597         touch one/file two/file &&
598         git add -A &&
599         git commit -m "Common commit" &&
600
601         git rm -rf one &&
602         git mv original one &&
603         git commit -m "Rename to one" &&
604
605         git checkout -b second-rename-redo HEAD~1 &&
606         git rm -rf two &&
607         git mv original two &&
608         git commit -m "Rename to two"
609 '
610
611 test_expect_success 'check handling of differently renamed file with D/F conflicts' '
612         git checkout -q first-rename-redo^0 &&
613         test_must_fail git merge --strategy=recursive second-rename-redo &&
614
615         test 3 -eq "$(git ls-files -u | wc -l)" &&
616         test 1 -eq "$(git ls-files -u one | wc -l)" &&
617         test 1 -eq "$(git ls-files -u two | wc -l)" &&
618         test 1 -eq "$(git ls-files -u original | wc -l)" &&
619         test 0 -eq "$(git ls-files -o | wc -l)" &&
620
621         test_path_is_file one &&
622         test_path_is_file two &&
623         test_path_is_missing original
624 '
625
626 test_expect_success 'setup avoid unnecessary update, normal rename' '
627         git reset --hard &&
628         git checkout --orphan avoid-unnecessary-update-1 &&
629         git rm -rf . &&
630         git clean -fdqx &&
631
632         printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >original &&
633         git add -A &&
634         git commit -m "Common commit" &&
635
636         git mv original rename &&
637         echo 11 >>rename &&
638         git add -u &&
639         git commit -m "Renamed and modified" &&
640
641         git checkout -b merge-branch-1 HEAD~1 &&
642         echo "random content" >random-file &&
643         git add -A &&
644         git commit -m "Random, unrelated changes"
645 '
646
647 test_expect_success 'avoid unnecessary update, normal rename' '
648         git checkout -q avoid-unnecessary-update-1^0 &&
649         test-tool chmtime --get -3600 rename >expect &&
650         git merge merge-branch-1 &&
651         test-tool chmtime --get rename >actual &&
652         test_cmp expect actual # "rename" should have stayed intact
653 '
654
655 test_expect_success 'setup to test avoiding unnecessary update, with D/F conflict' '
656         git reset --hard &&
657         git checkout --orphan avoid-unnecessary-update-2 &&
658         git rm -rf . &&
659         git clean -fdqx &&
660
661         mkdir df &&
662         printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >df/file &&
663         git add -A &&
664         git commit -m "Common commit" &&
665
666         git mv df/file temp &&
667         rm -rf df &&
668         git mv temp df &&
669         echo 11 >>df &&
670         git add -u &&
671         git commit -m "Renamed and modified" &&
672
673         git checkout -b merge-branch-2 HEAD~1 &&
674         >unrelated-change &&
675         git add unrelated-change &&
676         git commit -m "Only unrelated changes"
677 '
678
679 test_expect_success 'avoid unnecessary update, with D/F conflict' '
680         git checkout -q avoid-unnecessary-update-2^0 &&
681         test-tool chmtime --get -3600 df >expect &&
682         git merge merge-branch-2 &&
683         test-tool chmtime --get df >actual &&
684         test_cmp expect actual # "df" should have stayed intact
685 '
686
687 test_expect_success 'setup avoid unnecessary update, dir->(file,nothing)' '
688         git rm -rf . &&
689         git clean -fdqx &&
690         rm -rf .git &&
691         git init &&
692
693         >irrelevant &&
694         mkdir df &&
695         >df/file &&
696         git add -A &&
697         git commit -mA &&
698
699         git checkout -b side &&
700         git rm -rf df &&
701         git commit -mB &&
702
703         git checkout master &&
704         git rm -rf df &&
705         echo bla >df &&
706         git add -A &&
707         git commit -m "Add a newfile"
708 '
709
710 test_expect_success 'avoid unnecessary update, dir->(file,nothing)' '
711         git checkout -q master^0 &&
712         test-tool chmtime --get -3600 df >expect &&
713         git merge side &&
714         test-tool chmtime --get df >actual &&
715         test_cmp expect actual # "df" should have stayed intact
716 '
717
718 test_expect_success 'setup avoid unnecessary update, modify/delete' '
719         git rm -rf . &&
720         git clean -fdqx &&
721         rm -rf .git &&
722         git init &&
723
724         >irrelevant &&
725         >file &&
726         git add -A &&
727         git commit -mA &&
728
729         git checkout -b side &&
730         git rm -f file &&
731         git commit -m "Delete file" &&
732
733         git checkout master &&
734         echo bla >file &&
735         git add -A &&
736         git commit -m "Modify file"
737 '
738
739 test_expect_success 'avoid unnecessary update, modify/delete' '
740         git checkout -q master^0 &&
741         test-tool chmtime --get -3600 file >expect &&
742         test_must_fail git merge side &&
743         test-tool chmtime --get file >actual &&
744         test_cmp expect actual # "file" should have stayed intact
745 '
746
747 test_expect_success 'setup avoid unnecessary update, rename/add-dest' '
748         git rm -rf . &&
749         git clean -fdqx &&
750         rm -rf .git &&
751         git init &&
752
753         printf "1\n2\n3\n4\n5\n6\n7\n8\n" >file &&
754         git add -A &&
755         git commit -mA &&
756
757         git checkout -b side &&
758         cp file newfile &&
759         git add -A &&
760         git commit -m "Add file copy" &&
761
762         git checkout master &&
763         git mv file newfile &&
764         git commit -m "Rename file"
765 '
766
767 test_expect_success 'avoid unnecessary update, rename/add-dest' '
768         git checkout -q master^0 &&
769         test-tool chmtime --get -3600 newfile >expect &&
770         git merge side &&
771         test-tool chmtime --get newfile >actual &&
772         test_cmp expect actual # "file" should have stayed intact
773 '
774
775 test_expect_success 'setup merge of rename + small change' '
776         git reset --hard &&
777         git checkout --orphan rename-plus-small-change &&
778         git rm -rf . &&
779         git clean -fdqx &&
780
781         echo ORIGINAL >file &&
782         git add file &&
783
784         test_tick &&
785         git commit -m Initial &&
786         git checkout -b rename_branch &&
787         git mv file renamed_file &&
788         git commit -m Rename &&
789         git checkout rename-plus-small-change &&
790         echo NEW-VERSION >file &&
791         git commit -a -m Reformat
792 '
793
794 test_expect_success 'merge rename + small change' '
795         git merge rename_branch &&
796
797         test 1 -eq $(git ls-files -s | wc -l) &&
798         test 0 -eq $(git ls-files -o | wc -l) &&
799         test $(git rev-parse HEAD:renamed_file) = $(git rev-parse HEAD~1:file)
800 '
801
802 test_expect_success 'setup for use of extended merge markers' '
803         git rm -rf . &&
804         git clean -fdqx &&
805         rm -rf .git &&
806         git init &&
807
808         printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
809         git add original_file &&
810         git commit -mA &&
811
812         git checkout -b rename &&
813         echo 9 >>original_file &&
814         git add original_file &&
815         git mv original_file renamed_file &&
816         git commit -mB &&
817
818         git checkout master &&
819         echo 8.5 >>original_file &&
820         git add original_file &&
821         git commit -mC
822 '
823
824 test_expect_success 'merge master into rename has correct extended markers' '
825         git checkout rename^0 &&
826         test_must_fail git merge -s recursive master^0 &&
827
828         cat >expected <<-\EOF &&
829         1
830         2
831         3
832         4
833         5
834         6
835         7
836         8
837         <<<<<<< HEAD:renamed_file
838         9
839         =======
840         8.5
841         >>>>>>> master^0:original_file
842         EOF
843         test_cmp expected renamed_file
844 '
845
846 test_expect_success 'merge rename into master has correct extended markers' '
847         git reset --hard &&
848         git checkout master^0 &&
849         test_must_fail git merge -s recursive rename^0 &&
850
851         cat >expected <<-\EOF &&
852         1
853         2
854         3
855         4
856         5
857         6
858         7
859         8
860         <<<<<<< HEAD:original_file
861         8.5
862         =======
863         9
864         >>>>>>> rename^0:renamed_file
865         EOF
866         test_cmp expected renamed_file
867 '
868
869 test_expect_success 'setup spurious "refusing to lose untracked" message' '
870         git rm -rf . &&
871         git clean -fdqx &&
872         rm -rf .git &&
873         git init &&
874
875         > irrelevant_file &&
876         printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file &&
877         git add irrelevant_file original_file &&
878         git commit -mA &&
879
880         git checkout -b rename &&
881         git mv original_file renamed_file &&
882         git commit -mB &&
883
884         git checkout master &&
885         git rm original_file &&
886         git commit -mC
887 '
888
889 test_expect_success 'no spurious "refusing to lose untracked" message' '
890         git checkout master^0 &&
891         test_must_fail git merge rename^0 2>errors.txt &&
892         ! grep "refusing to lose untracked file" errors.txt
893 '
894
895 test_expect_success 'do not follow renames for empty files' '
896         git checkout -f -b empty-base &&
897         >empty1 &&
898         git add empty1 &&
899         git commit -m base &&
900         echo content >empty1 &&
901         git add empty1 &&
902         git commit -m fill &&
903         git checkout -b empty-topic HEAD^ &&
904         git mv empty1 empty2 &&
905         git commit -m rename &&
906         test_must_fail git merge empty-base &&
907         test_must_be_empty empty2
908 '
909
910 test_done