Raw
1 #!/bin/sh
2
3 test_description='tests for git-history squash subcommand'
4
5 . ./test-lib.sh
6
7 stage_file () {
8 printf "%s\n" "$1" >file &&
9 git add file
10 }
11
12 commit_with_message () {
13 printf "%b" "$1" >msg &&
14 git commit --allow-empty -qF msg
15 }
16
17 check_commit_count () {
18 git rev-list --count "$1" >actual &&
19 echo "$2" >expect &&
20 test_cmp expect actual
21 }
22
23 check_log_subjects () {
24 git log --format="%s" "$1" >actual &&
25 cat >expect &&
26 test_cmp expect actual
27 }
28
29 check_log_messages () {
30 git log --format="%B" "$1" >actual &&
31 cat >expect &&
32 test_cmp expect actual
33 }
34
35 test_expect_success 'setup linear history touching two files' '
36 test_commit base file a &&
37 git tag start &&
38 test_commit --no-tag one other x &&
39 test_commit --no-tag two file c &&
40 test_commit three file d
41 '
42
43 test_expect_success 'errors on missing range argument' '
44 test_must_fail git history squash 2>err &&
45 test_grep "expects a revision range" err
46 '
47
48 test_expect_success 'errors on an empty range' '
49 test_must_fail git history squash HEAD..HEAD 2>err &&
50 test_grep "the revision range is empty" err
51 '
52
53 test_expect_success 'errors on a single revision that is not a range' '
54 test_must_fail git history squash HEAD 2>err &&
55 test_grep "not a .*range" err &&
56 test_must_fail git history squash HEAD~1 2>err &&
57 test_grep "not a .*range" err
58 '
59
60 test_expect_success 'errors on a range holding a single commit' '
61 git reset --hard three &&
62 head_before=$(git rev-parse HEAD) &&
63
64 test_must_fail git history squash "HEAD^!" 2>err &&
65 test_grep "single commit; nothing to squash" err &&
66 test_cmp_rev "$head_before" HEAD
67 '
68
69 test_expect_success 'accepts multiple revision arguments with an exclusion' '
70 git reset --hard three &&
71 git branch -f keep HEAD~2 &&
72 tip_tree=$(git rev-parse HEAD^{tree}) &&
73
74 git history squash start..HEAD ^keep &&
75
76 git reflog -1 --format=%gs >actual &&
77 echo "squash: updating start..HEAD ^keep" >expect &&
78 test_cmp expect actual &&
79
80 check_log_subjects start..HEAD <<-\EOF &&
81 two
82 one
83 EOF
84 test_cmp_rev keep HEAD~1 &&
85 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
86
87 git branch -D keep
88 '
89
90 test_expect_success 'squashes a branch the current branch is not on' '
91 git reset --hard three &&
92 main=$(git symbolic-ref --short HEAD) &&
93 head_before=$(git rev-parse HEAD) &&
94 git checkout -b off-history start &&
95 test_commit --no-tag off-one off a &&
96 test_commit --no-tag off-two off b &&
97 git checkout "$main" &&
98
99 git history squash start..off-history &&
100
101 check_commit_count start..off-history 1 &&
102 test_cmp_rev "$head_before" HEAD &&
103
104 git branch -D off-history
105 '
106
107 test_expect_success 'squashes a range into a single commit without changing the tree' '
108 git reset --hard three &&
109 head_before=$(git rev-parse HEAD) &&
110 tip_tree=$(git rev-parse HEAD^{tree}) &&
111
112 git history squash --dry-run start.. >out &&
113 predicted=$(awk "/^update refs\/heads\// {print \$3}" out) &&
114 test_cmp_rev "$head_before" HEAD &&
115
116 git history squash start.. &&
117
118 test "$predicted" = "$(git rev-parse HEAD)" &&
119 check_commit_count start..HEAD 1 &&
120 test_cmp_rev start HEAD^ &&
121 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
122 check_log_subjects -1 <<-\EOF &&
123 one
124 EOF
125 git reflog >reflog &&
126 test_grep "squash: updating" reflog
127 '
128
129 test_expect_success 'sanitizes rev-list walk options, before and after --' '
130 git reset --hard three &&
131 tip_tree=$(git rev-parse HEAD^{tree}) &&
132
133 git history squash --date-order start.. 2>err &&
134 test_grep "ignoring rev-list options" err &&
135 test_cmp_rev start HEAD^ &&
136 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
137
138 git reset --hard three &&
139 git history squash -- --reverse start.. 2>err &&
140 test_grep "ignoring rev-list options" err &&
141 test_cmp_rev start HEAD^ &&
142 test "$tip_tree" = "$(git rev-parse HEAD^{tree})"
143 '
144
145 test_expect_success 'squashes an interior range and replays descendants verbatim' '
146 git reset --hard three &&
147 final_tree=$(git rev-parse HEAD^{tree}) &&
148
149 git history squash start..@~1 &&
150
151 check_log_subjects start..HEAD <<-\EOF &&
152 three
153 one
154 EOF
155
156 test_cmp_rev start HEAD~2 &&
157 test "$final_tree" = "$(git rev-parse HEAD^{tree})"
158 '
159
160 test_expect_success 'squashes when the base is the root commit' '
161 git reset --hard three &&
162 root=$(git rev-list --max-parents=0 HEAD) &&
163 tip_tree=$(git rev-parse HEAD^{tree}) &&
164
165 git history squash "$root.." &&
166
167 check_commit_count "$root..HEAD" 1 &&
168 test_cmp_rev "$root" HEAD^ &&
169 test "$tip_tree" = "$(git rev-parse HEAD^{tree})"
170 '
171
172
173 test_expect_success 'folds fixups whose target is in the range' '
174 git reset --hard start &&
175 test_commit --no-tag target file b &&
176 git commit --allow-empty -m "fixup! target" &&
177 git commit --allow-empty -m "fixup! target" &&
178 test_commit --no-tag later file c &&
179
180 git history squash start.. &&
181
182 check_commit_count start..HEAD 1 &&
183 check_log_subjects -1 <<-\EOF
184 target
185 EOF
186 '
187
188 test_expect_success 'refuses a below-range fixup! after an in-range commit' '
189 git reset --hard start &&
190 test_commit --no-tag inside file b &&
191 test_commit --no-tag "fixup! outside" file c &&
192 head_before=$(git rev-parse HEAD) &&
193
194 test_must_fail git history squash start.. 2>err &&
195 test_grep "target is not in the range" err &&
196 test_cmp_rev "$head_before" HEAD
197 '
198
199 test_expect_success 'combines a run of fixups for one commit below the range' '
200 git reset --hard start &&
201 stage_file b && git commit -m "fixup! base" &&
202 stage_file c && git commit -m "fixup! base" &&
203
204 git history squash start.. &&
205
206 check_commit_count start..HEAD 1 &&
207 check_log_subjects -1 <<-\EOF
208 fixup! base
209 EOF
210 '
211
212 test_expect_success 'combining below-range fixups keeps the last amend! message' '
213 git reset --hard start &&
214 stage_file b && git commit -m "fixup! base" &&
215 stage_file c &&
216 commit_with_message "amend! base\n\namended body\n" &&
217
218 git history squash start.. &&
219
220 check_commit_count start..HEAD 1 &&
221 check_log_messages -1 <<-\EOF
222 amend! base
223
224 amended body
225
226 EOF
227 '
228
229 test_expect_success 'refuses fixups for two different commits below the range' '
230 git reset --hard start &&
231 stage_file b && git commit -m "fixup! aaa" &&
232 stage_file c && git commit -m "fixup! bbb" &&
233 head_before=$(git rev-parse HEAD) &&
234
235 test_must_fail git history squash start.. 2>err &&
236 test_grep "target is not in the range" err &&
237 test_cmp_rev "$head_before" HEAD
238 '
239
240 test_expect_success 'the last amend! for the oldest commit replaces its message' '
241 git reset --hard start &&
242 test_commit --no-tag marker-oldest file b &&
243 git commit --allow-empty -m "squash! marker-oldest" &&
244 commit_with_message "amend! marker-oldest\n\nearlier message\n" &&
245 commit_with_message \
246 "amend! marker-oldest\n\namended subject\n\namended body\n" &&
247 test_commit --no-tag marker-later file c &&
248 commit_with_message "amend! marker-later\n\nwrong message\n" &&
249
250 git history squash start.. &&
251
252 check_commit_count start..HEAD 1 &&
253 check_log_messages -1 <<-\EOF
254 amended subject
255
256 amended body
257
258 EOF
259 '
260
261 test_expect_success 'preserves authorship of the oldest commit' '
262 git reset --hard start &&
263 GIT_AUTHOR_NAME=Squasher GIT_AUTHOR_EMAIL=squash@example.com \
264 test_commit --no-tag oldest file b &&
265 test_commit newest file c &&
266
267 git history squash start.. &&
268
269 git log -1 --format="%an <%ae>" >actual &&
270 echo "Squasher <squash@example.com>" >expect &&
271 test_cmp expect actual
272 '
273
274 test_expect_success '--reedit-message offers every folded-in message' '
275 git reset --hard start &&
276 stage_file b &&
277 git commit -m "re-one subject" -m "re-one body line" &&
278 test_commit --no-tag re-two file c &&
279 test_commit re-three file d &&
280
281 write_script editor <<-\EOF &&
282 cat "$1" >edited &&
283 echo combined >"$1"
284 EOF
285 test_set_editor "$(pwd)/editor" &&
286 git history squash --reedit-message start.. &&
287
288 cat >expect <<-EOF &&
289 # This is a combination of 3 commits.
290 # This is the 1st commit message:
291
292 re-one subject
293
294 re-one body line
295
296 # This is the commit message #2:
297
298 re-two
299
300 # This is the commit message #3:
301
302 re-three
303
304 # Please enter the commit message for the squash changes. Lines starting
305 # with ${SQ}#${SQ} will be ignored, and an empty message aborts the commit.
306 # Changes to be committed:
307 # modified: file
308 #
309 EOF
310 test_cmp expect edited &&
311 check_log_subjects -1 <<-\EOF
312 combined
313 EOF
314 '
315
316 test_expect_success '--reedit-message handles fixup!, squash! and amend! like rebase' '
317 git reset --hard start &&
318 test_commit --no-tag mark-base file b &&
319 stage_file c &&
320 commit_with_message "fixup! mark-base\n\nfixup body\n" &&
321 stage_file d &&
322 commit_with_message "squash! mark-base\n\nsquash remark\n" &&
323 stage_file e &&
324 commit_with_message "amend! mark-base\n\namended message\n" &&
325
326 write_script editor <<-\EOF &&
327 cat "$1" >edited
328 EOF
329 test_set_editor "$(pwd)/editor" &&
330 git history squash --reedit-message start.. &&
331
332 cat >expect <<-EOF &&
333 # This is a combination of 4 commits.
334 # This is the 1st commit message:
335
336 mark-base
337
338 # The commit message #2 will be skipped:
339
340 # fixup! mark-base
341 #
342 # fixup body
343
344 # This is the commit message #3:
345
346 # squash! mark-base
347
348 squash remark
349
350 # This is the commit message #4:
351
352 # amend! mark-base
353
354 amended message
355
356 # Please enter the commit message for the squash changes. Lines starting
357 # with ${SQ}#${SQ} will be ignored, and an empty message aborts the commit.
358 # Changes to be committed:
359 # modified: file
360 #
361 EOF
362 test_cmp expect edited &&
363 check_log_messages -1 <<-\EOF
364 mark-base
365
366 squash remark
367
368 amended message
369
370 EOF
371 '
372
373 test_expect_success '--reedit-message groups fixups under their targets' '
374 git reset --hard start &&
375 test_commit --no-tag alpha file a1 &&
376 test_commit --no-tag beta file b1 &&
377 stage_file a2 &&
378 commit_with_message "fixup! alpha\n" &&
379 stage_file b2 &&
380 commit_with_message "fixup! beta\n" &&
381
382 write_script editor <<-\EOF &&
383 cat "$1" >edited
384 EOF
385 test_set_editor "$(pwd)/editor" &&
386 git history squash --reedit-message start.. &&
387
388 cat >expect <<-EOF &&
389 # This is a combination of 4 commits.
390 # This is the 1st commit message:
391
392 alpha
393
394 # The commit message #2 will be skipped:
395
396 # fixup! alpha
397
398 # This is the commit message #3:
399
400 beta
401
402 # The commit message #4 will be skipped:
403
404 # fixup! beta
405
406 # Please enter the commit message for the squash changes. Lines starting
407 # with ${SQ}#${SQ} will be ignored, and an empty message aborts the commit.
408 # Changes to be committed:
409 # modified: file
410 #
411 EOF
412 test_cmp expect edited
413 '
414
415 test_expect_success '--reedit-message lets amend! replace its target message' '
416 git reset --hard start &&
417 test_commit --no-tag mark-base file b &&
418 stage_file c &&
419 commit_with_message "amend! mark-base\n\namended message\n" &&
420 stage_file d &&
421 commit_with_message "squash! mark-base\n\nsquash remark\n" &&
422
423 write_script editor <<-\EOF &&
424 cat "$1" >edited
425 EOF
426 test_set_editor "$(pwd)/editor" &&
427 git history squash --reedit-message start.. &&
428
429 cat >expect <<-EOF &&
430 # This is a combination of 3 commits.
431 # The 1st commit message will be skipped:
432
433 # mark-base
434
435 # This is the commit message #2:
436
437 # amend! mark-base
438
439 amended message
440
441 # This is the commit message #3:
442
443 # squash! mark-base
444
445 squash remark
446
447 # Please enter the commit message for the squash changes. Lines starting
448 # with ${SQ}#${SQ} will be ignored, and an empty message aborts the commit.
449 # Changes to be committed:
450 # modified: file
451 #
452 EOF
453 test_cmp expect edited &&
454 check_log_messages -1 <<-\EOF
455 amended message
456
457 squash remark
458
459 EOF
460 '
461
462 test_expect_success '--reedit-message aborts on an empty message' '
463 git reset --hard three &&
464 head_before=$(git rev-parse HEAD) &&
465
466 write_script editor <<-\EOF &&
467 >"$1"
468 EOF
469 test_set_editor "$(pwd)/editor" &&
470 test_must_fail git history squash --reedit-message start.. &&
471
472 test_cmp_rev "$head_before" HEAD
473 '
474
475 test_expect_success '--update-refs=head only moves HEAD' '
476 git reset --hard three &&
477 git branch -f other HEAD &&
478 other_before=$(git rev-parse other) &&
479
480 git history squash --update-refs=head start.. &&
481
482 check_commit_count start..HEAD 1 &&
483 test_cmp_rev "$other_before" other
484 '
485
486 test_expect_success 'refuses to fold a range a ref points into' '
487 git reset --hard three &&
488 git branch -f mid HEAD~1 &&
489 head_before=$(git rev-parse HEAD) &&
490
491 test_must_fail git history squash start.. 2>err &&
492 test_grep "error: .* points into the squashed range" err &&
493 test_grep "hint: .*--update-refs=head" err &&
494 test_cmp_rev "$head_before" HEAD &&
495
496 git branch -D mid
497 '
498
499 test_expect_success 'advice.historyUpdateRefs silences the hint' '
500 git reset --hard three &&
501 git branch -f mid HEAD~1 &&
502 head_before=$(git rev-parse HEAD) &&
503
504 test_must_fail git -c advice.historyUpdateRefs=false \
505 history squash start.. 2>err &&
506 test_grep "points into the squashed range" err &&
507 test_grep ! "hint:" err &&
508 test_cmp_rev "$head_before" HEAD &&
509
510 git branch -D mid
511 '
512
513 test_expect_success '--update-refs=head folds past a ref pointing into the range' '
514 git reset --hard three &&
515 git branch -f mid HEAD~1 &&
516 mid_before=$(git rev-parse mid) &&
517
518 git history squash --update-refs=head start.. &&
519
520 check_commit_count start..HEAD 1 &&
521 test_cmp_rev "$mid_before" mid &&
522
523 git branch -D mid
524 '
525
526 test_expect_success 'refuses to fold a range a tag points into' '
527 git reset --hard three &&
528 git tag -f mark HEAD~1 &&
529 head_before=$(git rev-parse HEAD) &&
530
531 test_must_fail git history squash start.. 2>err &&
532 test_grep "refs/tags/mark" err &&
533 test_grep "points into the squashed range" err &&
534 test_cmp_rev "$head_before" HEAD &&
535
536 git tag -d mark
537 '
538
539 test_expect_success 'squashes a range whose internal merge has a single base' '
540 git reset --hard start &&
541 main=$(git symbolic-ref --short HEAD) &&
542 test_commit --no-tag before-side file b &&
543 git checkout -b inner-side &&
544 test_commit --no-tag on-inner-side inner x &&
545 git checkout "$main" &&
546 test_commit --no-tag after-side file c &&
547 git merge --no-ff -m merge inner-side &&
548 git branch -D inner-side &&
549 test_commit --no-tag after-merge file d &&
550 tip_tree=$(git rev-parse HEAD^{tree}) &&
551
552 git history squash start.. &&
553
554 check_commit_count start..HEAD 1 &&
555 check_log_subjects -1 <<-\EOF &&
556 before-side
557 EOF
558 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
559 test_path_is_file inner
560 '
561
562 test_expect_success 'folds a merge of a branch that forked at the base' '
563 git reset --hard start &&
564 main=$(git symbolic-ref --short HEAD) &&
565 git checkout -b base-fork-side &&
566 test_commit --no-tag base-fork-side side x &&
567 git checkout "$main" &&
568 test_commit --no-tag base-fork-main file b &&
569 git merge --no-ff -m "merge base-fork-side" base-fork-side &&
570 git branch -D base-fork-side &&
571 test_commit --no-tag base-fork-tail file c &&
572 tip_tree=$(git rev-parse HEAD^{tree}) &&
573
574 git history squash start.. &&
575
576 check_commit_count start..HEAD 1 &&
577 test_cmp_rev start HEAD^ &&
578 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
579 test_path_is_file side
580 '
581
582 test_expect_success 'refuses a merge whose other parent is outside the range' '
583 git reset --hard start &&
584 main=$(git symbolic-ref --short HEAD) &&
585 git checkout -b outside-parent &&
586 test_commit --no-tag outside-parent outside x &&
587 git checkout "$main" &&
588 test_commit --no-tag outside-main file b &&
589 base=$(git rev-parse HEAD) &&
590 test_commit --no-tag outside-mid file c &&
591 git merge --no-ff -m "merge outside-parent" outside-parent &&
592 git branch -D outside-parent &&
593 merged=$(git rev-parse HEAD) &&
594
595 test_must_fail git history squash "$base.." 2>err &&
596 test_grep "more than one base" err &&
597 test_cmp_rev "$merged" HEAD
598 '
599
600 test_expect_success 'folds a range whose tip is a merge commit' '
601 git reset --hard start &&
602 main=$(git symbolic-ref --short HEAD) &&
603 test_commit --no-tag tipmerge-base file b &&
604 git checkout -b tipmerge-side &&
605 test_commit --no-tag tipmerge-side side x &&
606 git checkout "$main" &&
607 test_commit --no-tag tipmerge-main file c &&
608 git merge --no-ff -m "merge tipmerge-side" tipmerge-side &&
609 git branch -D tipmerge-side &&
610 tip_tree=$(git rev-parse HEAD^{tree}) &&
611
612 git history squash start.. &&
613
614 check_commit_count start..HEAD 1 &&
615 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
616 test_path_is_file side
617 '
618
619 test_expect_success 'folds a range whose base is a merge commit' '
620 git reset --hard start &&
621 main=$(git symbolic-ref --short HEAD) &&
622 git checkout -b basemerge-side &&
623 test_commit --no-tag basemerge-side side x &&
624 git checkout "$main" &&
625 test_commit --no-tag basemerge-main file b &&
626 git merge --no-ff -m "merge basemerge-side" basemerge-side &&
627 git branch -D basemerge-side &&
628 base=$(git rev-parse HEAD) &&
629 test_commit --no-tag basemerge-one file c &&
630 test_commit --no-tag basemerge-two file d &&
631 tip_tree=$(git rev-parse HEAD^{tree}) &&
632
633 git history squash "$base.." &&
634
635 check_commit_count "$base..HEAD" 1 &&
636 test_cmp_rev "$base" HEAD^ &&
637 test "$tip_tree" = "$(git rev-parse HEAD^{tree})"
638 '
639
640 test_expect_success 'folds a range with two interior merges' '
641 git reset --hard start &&
642 main=$(git symbolic-ref --short HEAD) &&
643 test_commit --no-tag two-merge-a file a1 &&
644 git checkout -b two-merge-s1 &&
645 test_commit --no-tag two-merge-s1 s1 x &&
646 git checkout "$main" &&
647 git merge --no-ff -m "merge s1" two-merge-s1 &&
648 test_commit --no-tag two-merge-b file b1 &&
649 git checkout -b two-merge-s2 &&
650 test_commit --no-tag two-merge-s2 s2 y &&
651 git checkout "$main" &&
652 git merge --no-ff -m "merge s2" two-merge-s2 &&
653 git branch -D two-merge-s1 two-merge-s2 &&
654 tip_tree=$(git rev-parse HEAD^{tree}) &&
655
656 git history squash start.. &&
657
658 check_commit_count start..HEAD 1 &&
659 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
660 test_path_is_file s1 &&
661 test_path_is_file s2
662 '
663
664 test_expect_success 'folds a range with a nested merge' '
665 git reset --hard start &&
666 main=$(git symbolic-ref --short HEAD) &&
667 git checkout -b nested-outer &&
668 test_commit --no-tag nested-outer outer x &&
669 git checkout -b nested-inner &&
670 test_commit --no-tag nested-inner inner y &&
671 git checkout nested-outer &&
672 git merge --no-ff -m "merge inner" nested-inner &&
673 git checkout "$main" &&
674 test_commit --no-tag nested-main file b1 &&
675 git merge --no-ff -m "merge outer" nested-outer &&
676 git branch -D nested-outer nested-inner &&
677 tip_tree=$(git rev-parse HEAD^{tree}) &&
678
679 git history squash start.. &&
680
681 check_commit_count start..HEAD 1 &&
682 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
683 test_path_is_file outer &&
684 test_path_is_file inner
685 '
686
687 test_expect_success 'folds a range with an octopus merge' '
688 git reset --hard start &&
689 main=$(git symbolic-ref --short HEAD) &&
690 test_commit --no-tag octo-base file a1 &&
691 git checkout -b octo-1 &&
692 test_commit --no-tag octo-1 o1 x &&
693 git checkout "$main" &&
694 git checkout -b octo-2 &&
695 test_commit --no-tag octo-2 o2 y &&
696 git checkout "$main" &&
697 git merge --no-ff -m octopus octo-1 octo-2 &&
698 git branch -D octo-1 octo-2 &&
699 tip_tree=$(git rev-parse HEAD^{tree}) &&
700
701 git history squash start.. &&
702
703 check_commit_count start..HEAD 1 &&
704 test "$tip_tree" = "$(git rev-parse HEAD^{tree})" &&
705 test_path_is_file o1 &&
706 test_path_is_file o2
707 '
708
709 test_expect_success 'refuses an octopus merge with an arm forked before the base' '
710 git reset --hard start &&
711 main=$(git symbolic-ref --short HEAD) &&
712 git checkout -b octo-pre &&
713 test_commit octo-pre-side pside x &&
714 git checkout "$main" &&
715 test_commit octo-pre-main file b1 &&
716 octo_base=$(git rev-parse HEAD) &&
717 git checkout -b octo-within &&
718 test_commit --no-tag octo-within wside y &&
719 git checkout "$main" &&
720 git merge --no-ff -m octopus octo-pre octo-within &&
721 merged=$(git rev-parse HEAD) &&
722 git branch -D octo-pre octo-within &&
723
724 test_must_fail git history squash "$octo_base.." 2>err &&
725 test_grep "more than one base" err &&
726 test_cmp_rev "$merged" HEAD
727 '
728
729 test_expect_success 'refuses when a descendant above the range is a merge' '
730 git reset --hard start &&
731 main=$(git symbolic-ref --short HEAD) &&
732 test_commit --no-tag desc-one file b &&
733 test_commit --no-tag desc-two file c &&
734 git tag desc-tip &&
735 git checkout -b desc-above &&
736 test_commit --no-tag desc-above above x &&
737 git checkout "$main" &&
738 test_commit --no-tag desc-main file d &&
739 git merge --no-ff -m "merge desc-above" desc-above &&
740 git branch -D desc-above &&
741 head_before=$(git rev-parse HEAD) &&
742
743 test_must_fail git history squash start..desc-tip 2>err &&
744 test_grep "merge commits is not supported" err &&
745 test_cmp_rev "$head_before" HEAD
746 '
747
748 test_expect_success 'refuses to fold a range a ref points into at a merge' '
749 git reset --hard start &&
750 main=$(git symbolic-ref --short HEAD) &&
751 test_commit --no-tag refmerge-base file b &&
752 git checkout -b refmerge-side &&
753 test_commit --no-tag refmerge-side side x &&
754 git checkout "$main" &&
755 test_commit --no-tag refmerge-main file c &&
756 git merge --no-ff -m "interior merge" refmerge-side &&
757 git branch -D refmerge-side &&
758 git branch at-merge HEAD &&
759 test_commit --no-tag refmerge-tail file d &&
760 head_before=$(git rev-parse HEAD) &&
761
762 test_must_fail git history squash start.. 2>err &&
763 test_grep "at-merge" err &&
764 test_grep "points into the squashed range" err &&
765 test_cmp_rev "$head_before" HEAD &&
766
767 git branch -D at-merge
768 '
769
770 test_done