3 # Copyright (c) 2006 Johannes E. Schindelin
6 test_description
='git rerere
12 ! [second] prefer first over second
19 - [second] prefer first over second
25 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
26 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
30 test_expect_success
'setup' '
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.
46 git commit -q -a -m initial &&
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;
59 git checkout -b first &&
61 git commit -q -a -m first &&
63 git checkout -b second main &&
65 sed -e "s/To die, t/To die! T/" -e "s/Some title/Some Title/" >a1 &&
66 echo "* END *" >>a1 &&
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)' '
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 &&
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 &&
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) &&
122 test_expect_success
'rerere diff' '
123 git show first:a1 >a1 &&
124 cat >expect <<-\EOF &&
131 Whether '\''tis nobler in the mind to suffer
132 The slings and arrows of outrageous fortune,
134 The heart-ache and the thousand natural shocks
135 That flesh is heir to, '\''tis a consummation
136 Devoutly to be wish'\''d.
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;
156 git rerere diff >out &&
160 test_expect_success
'rerere status' '
162 git rerere status >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 &&
180 ! grep "^=======\$" 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 &&
196 test_expect_success
'leftover directory' '
199 test_must_fail git merge first &&
203 test_expect_success
'missing preimage' '
206 cp .git/post-saved $rr/postimage &&
207 test_must_fail git merge first &&
211 test_expect_success
'set up for garbage collection tests' '
213 echo Hello >$rr/preimage &&
214 echo World >$rr/postimage &&
216 sha2=$(test_oid deadbeef) &&
217 rr2=.git/rr-cache/$sha2 &&
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' '
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 &&
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 &&
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' '
284 git checkout -b fourth &&
288 git commit -m version1 &&
290 git checkout third &&
294 git commit -m version2 &&
296 test_must_fail git merge fourth &&
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 &&
311 git commit -m version1 &&
313 git checkout third &&
317 git commit -m 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 &&
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 &&
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 &&
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 &&
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 &&
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 &&
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 &&
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_grep [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_grep [Uu]sage help
448 cat early
&& printf "%s\n" "$@" && cat late
"$last"
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
() {
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 &&
471 test_seq 1 6 >early &&
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 &&
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 &&
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 &&
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 &&
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
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
546 test_must_fail git merge six.1 &&
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
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 &&
580 test_expect_success
'rerere with unexpected conflict markers does not crash' '
583 git checkout -b branch-1 main &&
586 git commit -q -m two &&
589 git checkout -b branch-2 main &&
592 git commit -q -a -m one &&
594 test_must_fail git merge branch-1 &&
595 echo "<<<<<<< a" >test &&
601 test_expect_success
'rerere with inner conflict markers' '
604 git checkout -b A main &&
607 git commit -q -m two &&
610 git commit -q -m three &&
613 git checkout -b B main &&
616 git commit -q -a -m one &&
618 test_must_fail git merge A~ &&
620 git commit -q -m "will solve conflicts later" &&
621 test_must_fail git merge A &&
623 echo "resolved" >test &&
625 git commit -q -m "solved conflict" &&
627 echo "resolved" >expect &&
629 git reset --hard HEAD~~ &&
630 test_must_fail git merge A~ &&
632 git commit -q -m "will solve conflicts later" &&
633 test_must_fail git merge A &&
635 test_cmp expect actual &&
638 git commit -m "rerere solved conflict" &&
639 git reset --hard HEAD~ &&
640 test_must_fail git merge A &&
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 &&
652 git commit -m original &&
654 git checkout -b A main &&
656 git commit -m "rename to A" &&
658 git checkout -b B main &&
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 &&
670 test_must_fail git merge B^0