Merge branch 'fixes/2.45.1/2.41' into fixes/2.45.1/2.42
[alt-git.git] / t / t4200-rerere.sh
blob7025cfdae539c5109df5a33a1e0ec6e7bfeeb688
1 #!/bin/sh
3 # Copyright (c) 2006 Johannes E. Schindelin
6 test_description='git rerere
8 ! [fifth] version1
9 ! [first] first
10 ! [fourth] version1
11 ! [main] initial
12 ! [second] prefer first over second
13 ! [third] version2
14 ------
15 + [third] version2
16 + [fifth] version1
17 + [fourth] version1
18 + + + [third^] third
19 - [second] prefer first over second
20 + + [first] first
21 + [second^] second
22 ++++++ [main] initial
25 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
26 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
28 . ./test-lib.sh
30 test_expect_success 'setup' '
31 cat >a1 <<-\EOF &&
32 Some title
33 ==========
34 Whether '\''tis nobler in the mind to suffer
35 The slings and arrows of outrageous fortune,
36 Or to take arms against a sea of troubles,
37 And by opposing end them? To die: to sleep;
38 No more; and by a sleep to say we end
39 The heart-ache and the thousand natural shocks
40 That flesh is heir to, '\''tis a consummation
41 Devoutly to be wish'\''d.
42 EOF
44 git add a1 &&
45 test_tick &&
46 git commit -q -a -m initial &&
48 cat >>a1 <<-\EOF &&
49 Some title
50 ==========
51 To die, to sleep;
52 To sleep: perchance to dream: ay, there'\''s the rub;
53 For in that sleep of death what dreams may come
54 When we have shuffled off this mortal coil,
55 Must give us pause: there'\''s the respect
56 That makes calamity of so long life;
57 EOF
59 git checkout -b first &&
60 test_tick &&
61 git commit -q -a -m first &&
63 git checkout -b second main &&
64 git show first:a1 |
65 sed -e "s/To die, t/To die! T/" -e "s/Some title/Some Title/" >a1 &&
66 echo "* END *" >>a1 &&
67 test_tick &&
68 git commit -q -a -m second
71 test_expect_success 'nothing recorded without rerere' '
72 rm -rf .git/rr-cache &&
73 git config rerere.enabled false &&
74 test_must_fail git merge first &&
75 ! test -d .git/rr-cache
78 test_expect_success 'activate rerere, old style (conflicting merge)' '
79 git reset --hard &&
80 mkdir .git/rr-cache &&
81 test_might_fail git config --unset rerere.enabled &&
82 test_must_fail git merge first &&
84 sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) &&
85 rr=.git/rr-cache/$sha1 &&
86 grep "^=======\$" $rr/preimage &&
87 ! test -f $rr/postimage &&
88 ! test -f $rr/thisimage
91 test_expect_success 'rerere.enabled works, too' '
92 rm -rf .git/rr-cache &&
93 git config rerere.enabled true &&
94 git reset --hard &&
95 test_must_fail git merge first &&
97 sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) &&
98 rr=.git/rr-cache/$sha1 &&
99 grep ^=======$ $rr/preimage
102 test_expect_success 'set up rr-cache' '
103 rm -rf .git/rr-cache &&
104 git config rerere.enabled true &&
105 git reset --hard &&
106 test_must_fail git merge first &&
107 sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) &&
108 rr=.git/rr-cache/$sha1
111 test_expect_success 'rr-cache looks sane' '
112 # no postimage or thisimage yet
113 ! test -f $rr/postimage &&
114 ! test -f $rr/thisimage &&
116 # preimage has right number of lines
117 cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) &&
118 echo $cnt &&
119 test $cnt = 13
122 test_expect_success 'rerere diff' '
123 git show first:a1 >a1 &&
124 cat >expect <<-\EOF &&
125 --- a/a1
126 +++ b/a1
127 @@ -1,4 +1,4 @@
128 -Some Title
129 +Some title
130 ==========
131 Whether '\''tis nobler in the mind to suffer
132 The slings and arrows of outrageous fortune,
133 @@ -8,21 +8,11 @@
134 The heart-ache and the thousand natural shocks
135 That flesh is heir to, '\''tis a consummation
136 Devoutly to be wish'\''d.
137 -<<<<<<<
138 -Some Title
139 -==========
140 -To die! To sleep;
141 -=======
142 Some title
143 ==========
144 To die, to sleep;
145 ->>>>>>>
146 To sleep: perchance to dream: ay, there'\''s the rub;
147 For in that sleep of death what dreams may come
148 When we have shuffled off this mortal coil,
149 Must give us pause: there'\''s the respect
150 That makes calamity of so long life;
151 -<<<<<<<
152 -=======
153 -* END *
154 ->>>>>>>
156 git rerere diff >out &&
157 test_cmp expect out
160 test_expect_success 'rerere status' '
161 echo a1 >expect &&
162 git rerere status >out &&
163 test_cmp expect out
166 test_expect_success 'first postimage wins' '
167 git show first:a1 | sed "s/To die: t/To die! T/" >expect &&
169 git commit -q -a -m "prefer first over second" &&
170 test -f $rr/postimage &&
172 oldmtimepost=$(test-tool chmtime --get -60 $rr/postimage) &&
174 git checkout -b third main &&
175 git show second^:a1 | sed "s/To die: t/To die! T/" >a1 &&
176 git commit -q -a -m third &&
178 test_must_fail git merge first &&
179 # rerere kicked in
180 ! grep "^=======\$" a1 &&
181 test_cmp expect a1
184 test_expect_success 'rerere updates postimage timestamp' '
185 newmtimepost=$(test-tool chmtime --get $rr/postimage) &&
186 test $oldmtimepost -lt $newmtimepost
189 test_expect_success 'rerere clear' '
190 mv $rr/postimage .git/post-saved &&
191 echo "$sha1 a1" | perl -pe "y/\012/\000/" >.git/MERGE_RR &&
192 git rerere clear &&
193 ! test -d $rr
196 test_expect_success 'leftover directory' '
197 git reset --hard &&
198 mkdir -p $rr &&
199 test_must_fail git merge first &&
200 test -f $rr/preimage
203 test_expect_success 'missing preimage' '
204 git reset --hard &&
205 mkdir -p $rr &&
206 cp .git/post-saved $rr/postimage &&
207 test_must_fail git merge first &&
208 test -f $rr/preimage
211 test_expect_success 'set up for garbage collection tests' '
212 mkdir -p $rr &&
213 echo Hello >$rr/preimage &&
214 echo World >$rr/postimage &&
216 sha2=$(test_oid deadbeef) &&
217 rr2=.git/rr-cache/$sha2 &&
218 mkdir $rr2 &&
219 echo Hello >$rr2/preimage &&
221 almost_15_days_ago=$((60-15*86400)) &&
222 just_over_15_days_ago=$((-1-15*86400)) &&
223 almost_60_days_ago=$((60-60*86400)) &&
224 just_over_60_days_ago=$((-1-60*86400)) &&
226 test-tool chmtime =$just_over_60_days_ago $rr/preimage &&
227 test-tool chmtime =$almost_60_days_ago $rr/postimage &&
228 test-tool chmtime =$almost_15_days_ago $rr2/preimage
231 test_expect_success 'gc preserves young or recently used records' '
232 git rerere gc &&
233 test -f $rr/preimage &&
234 test -f $rr2/preimage
237 test_expect_success 'old records rest in peace' '
238 test-tool chmtime =$just_over_60_days_ago $rr/postimage &&
239 test-tool chmtime =$just_over_15_days_ago $rr2/preimage &&
240 git rerere gc &&
241 ! test -f $rr/preimage &&
242 ! test -f $rr2/preimage
245 rerere_gc_custom_expiry_test () {
246 five_days="$1" right_now="$2"
247 test_expect_success "rerere gc with custom expiry ($five_days, $right_now)" '
248 rm -fr .git/rr-cache &&
249 rr=.git/rr-cache/$ZERO_OID &&
250 mkdir -p "$rr" &&
251 >"$rr/preimage" &&
252 >"$rr/postimage" &&
254 two_days_ago=$((-2*86400)) &&
255 test-tool chmtime =$two_days_ago "$rr/preimage" &&
256 test-tool chmtime =$two_days_ago "$rr/postimage" &&
258 find .git/rr-cache -type f | sort >original &&
260 git -c "gc.rerereresolved=$five_days" \
261 -c "gc.rerereunresolved=$five_days" rerere gc &&
262 find .git/rr-cache -type f | sort >actual &&
263 test_cmp original actual &&
265 git -c "gc.rerereresolved=$five_days" \
266 -c "gc.rerereunresolved=$right_now" rerere gc &&
267 find .git/rr-cache -type f | sort >actual &&
268 test_cmp original actual &&
270 git -c "gc.rerereresolved=$right_now" \
271 -c "gc.rerereunresolved=$right_now" rerere gc &&
272 find .git/rr-cache -type f | sort >actual &&
273 test_must_be_empty actual
277 rerere_gc_custom_expiry_test 5 0
279 rerere_gc_custom_expiry_test 5.days.ago now
281 test_expect_success 'setup: file2 added differently in two branches' '
282 git reset --hard &&
284 git checkout -b fourth &&
285 echo Hallo >file2 &&
286 git add file2 &&
287 test_tick &&
288 git commit -m version1 &&
290 git checkout third &&
291 echo Bello >file2 &&
292 git add file2 &&
293 test_tick &&
294 git commit -m version2 &&
296 test_must_fail git merge fourth &&
297 echo Cello >file2 &&
298 git add file2 &&
299 git commit -m resolution
302 test_expect_success 'resolution was recorded properly' '
303 echo Cello >expected &&
305 git reset --hard HEAD~2 &&
306 git checkout -b fifth &&
308 echo Hallo >file3 &&
309 git add file3 &&
310 test_tick &&
311 git commit -m version1 &&
313 git checkout third &&
314 echo Bello >file3 &&
315 git add file3 &&
316 test_tick &&
317 git commit -m version2 &&
318 git tag version2 &&
320 test_must_fail git merge fifth &&
321 test_cmp expected file3 &&
322 test_must_fail git update-index --refresh
325 test_expect_success 'rerere.autoupdate' '
326 git config rerere.autoupdate true &&
327 git reset --hard &&
328 git checkout version2 &&
329 test_must_fail git merge fifth &&
330 git update-index --refresh
333 test_expect_success 'merge --rerere-autoupdate' '
334 test_might_fail git config --unset rerere.autoupdate &&
335 git reset --hard &&
336 git checkout version2 &&
337 test_must_fail git merge --rerere-autoupdate fifth &&
338 git update-index --refresh
341 test_expect_success 'merge --no-rerere-autoupdate' '
342 headblob=$(git rev-parse version2:file3) &&
343 mergeblob=$(git rev-parse fifth:file3) &&
344 cat >expected <<-EOF &&
345 100644 $headblob 2 file3
346 100644 $mergeblob 3 file3
349 git config rerere.autoupdate true &&
350 git reset --hard &&
351 git checkout version2 &&
352 test_must_fail git merge --no-rerere-autoupdate fifth &&
353 git ls-files -u >actual &&
354 test_cmp expected actual
357 test_expect_success 'set up an unresolved merge' '
358 headblob=$(git rev-parse version2:file3) &&
359 mergeblob=$(git rev-parse fifth:file3) &&
360 cat >expected.unresolved <<-EOF &&
361 100644 $headblob 2 file3
362 100644 $mergeblob 3 file3
365 test_might_fail git config --unset rerere.autoupdate &&
366 git reset --hard &&
367 git checkout version2 &&
368 ancestor=$(git merge-base version2 fifth) &&
369 test_must_fail git merge-recursive "$ancestor" -- HEAD fifth &&
371 git ls-files --stage >failedmerge &&
372 cp file3 file3.conflict &&
374 git ls-files -u >actual &&
375 test_cmp expected.unresolved actual
378 test_expect_success 'explicit rerere' '
379 test_might_fail git config --unset rerere.autoupdate &&
380 git rm -fr --cached . &&
381 git update-index --index-info <failedmerge &&
382 cp file3.conflict file3 &&
383 test_must_fail git update-index --refresh -q &&
385 git rerere &&
386 git ls-files -u >actual &&
387 test_cmp expected.unresolved actual
390 test_expect_success 'explicit rerere with autoupdate' '
391 git config rerere.autoupdate true &&
392 git rm -fr --cached . &&
393 git update-index --index-info <failedmerge &&
394 cp file3.conflict file3 &&
395 test_must_fail git update-index --refresh -q &&
397 git rerere &&
398 git update-index --refresh
401 test_expect_success 'explicit rerere --rerere-autoupdate overrides' '
402 git config rerere.autoupdate false &&
403 git rm -fr --cached . &&
404 git update-index --index-info <failedmerge &&
405 cp file3.conflict file3 &&
406 git rerere &&
407 git ls-files -u >actual1 &&
409 git rm -fr --cached . &&
410 git update-index --index-info <failedmerge &&
411 cp file3.conflict file3 &&
412 git rerere --rerere-autoupdate &&
413 git update-index --refresh &&
415 git rm -fr --cached . &&
416 git update-index --index-info <failedmerge &&
417 cp file3.conflict file3 &&
418 git rerere --rerere-autoupdate --no-rerere-autoupdate &&
419 git ls-files -u >actual2 &&
421 git rm -fr --cached . &&
422 git update-index --index-info <failedmerge &&
423 cp file3.conflict file3 &&
424 git rerere --rerere-autoupdate --no-rerere-autoupdate --rerere-autoupdate &&
425 git update-index --refresh &&
427 test_cmp expected.unresolved actual1 &&
428 test_cmp expected.unresolved actual2
431 test_expect_success 'rerere --no-no-rerere-autoupdate' '
432 git rm -fr --cached . &&
433 git update-index --index-info <failedmerge &&
434 cp file3.conflict file3 &&
435 test_must_fail git rerere --no-no-rerere-autoupdate 2>err &&
436 test_i18ngrep [Uu]sage err &&
437 test_must_fail git update-index --refresh
440 test_expect_success 'rerere -h' '
441 test_must_fail git rerere -h >help &&
442 test_i18ngrep [Uu]sage help
445 concat_insert () {
446 last=$1
447 shift
448 cat early && printf "%s\n" "$@" && cat late "$last"
451 count_pre_post () {
452 find .git/rr-cache/ -type f -name "preimage*" >actual &&
453 test_line_count = "$1" actual &&
454 find .git/rr-cache/ -type f -name "postimage*" >actual &&
455 test_line_count = "$2" actual
458 merge_conflict_resolve () {
459 git reset --hard &&
460 test_must_fail git merge six.1 &&
461 # Resolution is to replace 7 with 6.1 and 6.2 (i.e. take both)
462 concat_insert short 6.1 6.2 >file1 &&
463 concat_insert long 6.1 6.2 >file2
466 test_expect_success 'multiple identical conflicts' '
467 rm -fr .git/rr-cache &&
468 mkdir .git/rr-cache &&
469 git reset --hard &&
471 test_seq 1 6 >early &&
472 >late &&
473 test_seq 11 15 >short &&
474 test_seq 111 120 >long &&
475 concat_insert short >file1 &&
476 concat_insert long >file2 &&
477 git add file1 file2 &&
478 git commit -m base &&
479 git tag base &&
480 git checkout -b six.1 &&
481 concat_insert short 6.1 >file1 &&
482 concat_insert long 6.1 >file2 &&
483 git add file1 file2 &&
484 git commit -m 6.1 &&
485 git checkout -b six.2 HEAD^ &&
486 concat_insert short 6.2 >file1 &&
487 concat_insert long 6.2 >file2 &&
488 git add file1 file2 &&
489 git commit -m 6.2 &&
491 # At this point, six.1 and six.2
492 # - derive from common ancestor that has two files
493 # 1...6 7 11..15 (file1) and 1...6 7 111..120 (file2)
494 # - six.1 replaces these 7s with 6.1
495 # - six.2 replaces these 7s with 6.2
497 merge_conflict_resolve &&
499 # Check that rerere knows that file1 and file2 have conflicts
501 printf "%s\n" file1 file2 >expect &&
502 git ls-files -u | sed -e "s/^.* //" | sort -u >actual &&
503 test_cmp expect actual &&
505 git rerere status | sort >actual &&
506 test_cmp expect actual &&
508 git rerere remaining >actual &&
509 test_cmp expect actual &&
511 count_pre_post 2 0 &&
513 # Pretend that the conflicts were made quite some time ago
514 test-tool chmtime -172800 $(find .git/rr-cache/ -type f) &&
516 # Unresolved entries have not expired yet
517 git -c gc.rerereresolved=5 -c gc.rerereunresolved=5 rerere gc &&
518 count_pre_post 2 0 &&
520 # Unresolved entries have expired
521 git -c gc.rerereresolved=5 -c gc.rerereunresolved=1 rerere gc &&
522 count_pre_post 0 0 &&
524 # Recreate the conflicted state
525 merge_conflict_resolve &&
526 count_pre_post 2 0 &&
528 # Clear it
529 git rerere clear &&
530 count_pre_post 0 0 &&
532 # Recreate the conflicted state
533 merge_conflict_resolve &&
534 count_pre_post 2 0 &&
536 # We resolved file1 and file2
537 git rerere &&
538 git rerere remaining >actual &&
539 test_must_be_empty actual &&
541 # We must have recorded both of them
542 count_pre_post 2 2 &&
544 # Now we should be able to resolve them both
545 git reset --hard &&
546 test_must_fail git merge six.1 &&
547 git rerere &&
549 git rerere remaining >actual &&
550 test_must_be_empty actual &&
552 concat_insert short 6.1 6.2 >file1.expect &&
553 concat_insert long 6.1 6.2 >file2.expect &&
554 test_cmp file1.expect file1 &&
555 test_cmp file2.expect file2 &&
557 # Forget resolution for file2
558 git rerere forget file2 &&
559 echo file2 >expect &&
560 git rerere status >actual &&
561 test_cmp expect actual &&
562 count_pre_post 2 1 &&
564 # file2 already has correct resolution, so record it again
565 git rerere &&
567 # Pretend that the resolutions are old again
568 test-tool chmtime -172800 $(find .git/rr-cache/ -type f) &&
570 # Resolved entries have not expired yet
571 git -c gc.rerereresolved=5 -c gc.rerereunresolved=5 rerere gc &&
573 count_pre_post 2 2 &&
575 # Resolved entries have expired
576 git -c gc.rerereresolved=1 -c gc.rerereunresolved=5 rerere gc &&
577 count_pre_post 0 0
580 test_expect_success 'rerere with unexpected conflict markers does not crash' '
581 git reset --hard &&
583 git checkout -b branch-1 main &&
584 echo "bar" >test &&
585 git add test &&
586 git commit -q -m two &&
588 git reset --hard &&
589 git checkout -b branch-2 main &&
590 echo "foo" >test &&
591 git add test &&
592 git commit -q -a -m one &&
594 test_must_fail git merge branch-1 &&
595 echo "<<<<<<< a" >test &&
596 git rerere &&
598 git rerere clear
601 test_expect_success 'rerere with inner conflict markers' '
602 git reset --hard &&
604 git checkout -b A main &&
605 echo "bar" >test &&
606 git add test &&
607 git commit -q -m two &&
608 echo "baz" >test &&
609 git add test &&
610 git commit -q -m three &&
612 git reset --hard &&
613 git checkout -b B main &&
614 echo "foo" >test &&
615 git add test &&
616 git commit -q -a -m one &&
618 test_must_fail git merge A~ &&
619 git add test &&
620 git commit -q -m "will solve conflicts later" &&
621 test_must_fail git merge A &&
623 echo "resolved" >test &&
624 git add test &&
625 git commit -q -m "solved conflict" &&
627 echo "resolved" >expect &&
629 git reset --hard HEAD~~ &&
630 test_must_fail git merge A~ &&
631 git add test &&
632 git commit -q -m "will solve conflicts later" &&
633 test_must_fail git merge A &&
634 cat test >actual &&
635 test_cmp expect actual &&
637 git add test &&
638 git commit -m "rerere solved conflict" &&
639 git reset --hard HEAD~ &&
640 test_must_fail git merge A &&
641 cat test >actual &&
642 test_cmp expect actual
645 test_expect_success 'setup simple stage 1 handling' '
646 test_create_repo stage_1_handling &&
648 cd stage_1_handling &&
650 test_seq 1 10 >original &&
651 git add original &&
652 git commit -m original &&
654 git checkout -b A main &&
655 git mv original A &&
656 git commit -m "rename to A" &&
658 git checkout -b B main &&
659 git mv original B &&
660 git commit -m "rename to B"
664 test_expect_success 'test simple stage 1 handling' '
666 cd stage_1_handling &&
668 git config rerere.enabled true &&
669 git checkout A^0 &&
670 test_must_fail git merge B^0
674 test_done