3 test_description
='auto squash'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10 .
"$TEST_DIRECTORY"/lib-rebase.sh
12 test_expect_success setup
'
16 git commit -m "initial commit" &&
21 git commit -m "first commit" &&
22 git tag first-commit &&
26 git commit -m "second commit" &&
38 git
reset --hard base
&&
42 git commit
-m "fixup! first" &&
46 git rebase
$2 HEAD^^^
&&
47 git log
--oneline >actual
&&
48 if test -n "$no_squash"
50 test_line_count
= 4 actual
52 test_line_count
= 3 actual
&&
53 git
diff --exit-code $1 &&
55 git cat-file blob HEAD^
:file1
>actual
&&
56 test_cmp expect actual
&&
57 git cat-file commit HEAD^
>commit
&&
58 grep first commit
>actual
&&
59 test_line_count
= 1 actual
63 test_expect_success
'auto fixup (option)' '
64 test_auto_fixup fixup-option --autosquash &&
65 test_auto_fixup fixup-option-i "--autosquash -i"
68 test_expect_success
'auto fixup (config true)' '
69 git config rebase.autosquash true &&
70 test_auto_fixup ! fixup-config-true &&
71 test_auto_fixup fixup-config-true-i -i &&
72 test_auto_fixup ! fixup-config-true-no --no-autosquash &&
73 test_auto_fixup ! fixup-config-true-i-no "-i --no-autosquash"
76 test_expect_success
'auto fixup (config false)' '
77 git config rebase.autosquash false &&
78 test_auto_fixup ! fixup-config-false &&
79 test_auto_fixup ! fixup-config-false-i -i &&
80 test_auto_fixup fixup-config-false-yes --autosquash &&
81 test_auto_fixup fixup-config-false-i-yes "-i --autosquash"
92 git
reset --hard base
&&
96 git commit
-m "squash! first" -m "extra para for first" &&
99 git rebase
$2 HEAD^^^
&&
100 git log
--oneline >actual
&&
101 if test -n "$no_squash"
103 test_line_count
= 4 actual
105 test_line_count
= 3 actual
&&
106 git
diff --exit-code $1 &&
108 git cat-file blob HEAD^
:file1
>actual
&&
109 test_cmp expect actual
&&
110 git cat-file commit HEAD^
>commit
&&
111 grep first commit
>actual
&&
112 test_line_count
= 2 actual
116 test_expect_success
'auto squash (option)' '
117 test_auto_squash squash-option --autosquash &&
118 test_auto_squash squash-option-i "--autosquash -i"
121 test_expect_success
'auto squash (config true)' '
122 git config rebase.autosquash true &&
123 test_auto_squash ! squash-config-true &&
124 test_auto_squash squash-config-true-i -i &&
125 test_auto_squash ! squash-config-true-no --no-autosquash &&
126 test_auto_squash ! squash-config-true-i-no "-i --no-autosquash"
129 test_expect_success
'auto squash (config false)' '
130 git config rebase.autosquash false &&
131 test_auto_squash ! squash-config-false &&
132 test_auto_squash ! squash-config-false-i -i &&
133 test_auto_squash squash-config-false-yes --autosquash &&
134 test_auto_squash squash-config-false-i-yes "-i --autosquash"
137 test_expect_success
'misspelled auto squash' '
138 git reset --hard base &&
142 git commit -m "squash! forst" &&
143 git tag final-missquash &&
145 git rebase --autosquash -i HEAD^^^ &&
146 git log --oneline >actual &&
147 test_line_count = 4 actual &&
148 git diff --exit-code final-missquash &&
149 git rev-list final-missquash...HEAD >list &&
150 test_must_be_empty list
153 test_expect_success
'auto squash that matches 2 commits' '
154 git reset --hard base &&
158 git commit -m "first new commit" &&
162 git commit -m "squash! first" -m "extra para for first" &&
163 git tag final-multisquash &&
165 git rebase --autosquash -i HEAD~4 &&
166 git log --oneline >actual &&
167 test_line_count = 4 actual &&
168 git diff --exit-code final-multisquash &&
170 git cat-file blob HEAD^^:file1 >actual &&
171 test_cmp expect actual &&
172 git cat-file commit HEAD^^ >commit &&
173 grep first commit >actual &&
174 test_line_count = 2 actual &&
175 git cat-file commit HEAD >commit &&
176 grep first commit >actual &&
177 test_line_count = 1 actual
180 test_expect_success
'auto squash that matches a commit after the squash' '
181 git reset --hard base &&
185 git commit -m "squash! third" &&
189 git commit -m "third commit" &&
190 git tag final-presquash &&
192 git rebase --autosquash -i HEAD~4 &&
193 git log --oneline >actual &&
194 test_line_count = 5 actual &&
195 git diff --exit-code final-presquash &&
197 git cat-file blob HEAD^^:file1 >actual &&
198 test_cmp expect actual &&
200 git cat-file blob HEAD^:file1 >actual &&
201 test_cmp expect actual &&
202 git cat-file commit HEAD >commit &&
203 grep third commit >actual &&
204 test_line_count = 1 actual &&
205 git cat-file commit HEAD^ >commit &&
206 grep third commit >actual &&
207 test_line_count = 1 actual
209 test_expect_success
'auto squash that matches a sha1' '
210 git reset --hard base &&
214 oid=$(git rev-parse --short HEAD^) &&
215 git commit -m "squash! $oid" -m "extra para" &&
216 git tag final-shasquash &&
218 git rebase --autosquash -i HEAD^^^ &&
219 git log --oneline >actual &&
220 test_line_count = 3 actual &&
221 git diff --exit-code final-shasquash &&
223 git cat-file blob HEAD^:file1 >actual &&
224 test_cmp expect actual &&
225 git cat-file commit HEAD^ >commit &&
226 ! grep "squash" commit &&
227 grep "^extra para" commit >actual &&
228 test_line_count = 1 actual
231 test_expect_success
'auto squash that matches longer sha1' '
232 git reset --hard base &&
236 oid=$(git rev-parse --short=11 HEAD^) &&
237 git commit -m "squash! $oid" -m "extra para" &&
238 git tag final-longshasquash &&
240 git rebase --autosquash -i HEAD^^^ &&
241 git log --oneline >actual &&
242 test_line_count = 3 actual &&
243 git diff --exit-code final-longshasquash &&
245 git cat-file blob HEAD^:file1 >actual &&
246 test_cmp expect actual &&
247 git cat-file commit HEAD^ >commit &&
248 ! grep "squash" commit &&
249 grep "^extra para" commit >actual &&
250 test_line_count = 1 actual
253 test_expect_success
'auto squash of fixup commit that matches branch name which points back to fixup commit' '
254 git reset --hard base &&
255 git commit --allow-empty -m "fixup! self-cycle" &&
256 git branch self-cycle &&
257 GIT_SEQUENCE_EDITOR="cat >tmp" git rebase --autosquash -i HEAD^^ &&
258 sed -ne "/^[^#]/{s/[0-9a-f]\{7,\}/HASH/g;p;}" tmp >actual &&
259 cat <<-EOF >expect &&
260 pick HASH second commit
261 pick HASH fixup! self-cycle # empty
263 test_cmp expect actual
266 test_auto_commit_flags
() {
267 git
reset --hard base
&&
271 git commit
--$1 first-commit
-m "extra para for first" &&
272 git tag final-commit-
$1 &&
274 git rebase
--autosquash -i HEAD^^^
&&
275 git log
--oneline >actual
&&
276 test_line_count
= 3 actual
&&
277 git
diff --exit-code final-commit-
$1 &&
279 git cat-file blob HEAD^
:file1
>actual
&&
280 test_cmp expect actual
&&
281 git cat-file commit HEAD^
>commit
&&
282 grep first commit
>actual
&&
283 test_line_count
= $2 actual
286 test_expect_success
'use commit --fixup' '
287 test_auto_commit_flags fixup 1
290 test_expect_success
'use commit --squash' '
291 test_auto_commit_flags squash 2
294 test_auto_fixup_fixup
() {
295 git
reset --hard base
&&
299 git commit
-m "$1! first" -m "extra para for first" &&
303 git commit
-m "$1! $2! first" -m "second extra para for first" &&
304 git tag
"final-$1-$2" &&
307 set_cat_todo_editor
&&
308 test_must_fail git rebase
--autosquash -i HEAD^^^^
>actual
&&
309 head=$
(git rev-parse
--short HEAD
) &&
310 parent1
=$
(git rev-parse
--short HEAD^
) &&
311 parent2
=$
(git rev-parse
--short HEAD^^
) &&
312 parent3
=$
(git rev-parse
--short HEAD^^^
) &&
313 cat >expected
<<-EOF &&
314 pick $parent3 first commit
315 $1 $parent1 $1! first
316 $1 $head $1! $2! first
317 pick $parent2 second commit
319 test_cmp expected actual
321 git rebase
--autosquash -i HEAD^^^^
&&
322 git log
--oneline >actual
&&
323 test_line_count
= 3 actual
324 git
diff --exit-code "final-$1-$2" &&
326 git cat-file blob HEAD^
:file1
>actual
&&
327 test_cmp expect actual
&&
328 git cat-file commit HEAD^
>commit
&&
329 grep first commit
>actual
&&
330 if test "$1" = "fixup"
332 test_line_count
= 1 actual
333 elif test "$1" = "squash"
335 test_line_count
= 3 actual
341 test_expect_success
'fixup! fixup!' '
342 test_auto_fixup_fixup fixup fixup
345 test_expect_success
'fixup! squash!' '
346 test_auto_fixup_fixup fixup squash
349 test_expect_success
'squash! squash!' '
350 test_auto_fixup_fixup squash squash
353 test_expect_success
'squash! fixup!' '
354 test_auto_fixup_fixup squash fixup
357 test_expect_success
'autosquash with custom inst format' '
358 git reset --hard base &&
359 git config --add rebase.instructionFormat "[%an @ %ar] %s" &&
363 oid=$(git rev-parse --short HEAD^) &&
364 git commit -m "squash! $oid" -m "extra para for first" &&
368 subject=$(git log -n 1 --format=%s HEAD~2) &&
369 git commit -m "squash! $subject" -m "second extra para for first" &&
370 git tag final-squash-instFmt &&
372 git rebase --autosquash -i HEAD~4 &&
373 git log --oneline >actual &&
374 test_line_count = 3 actual &&
375 git diff --exit-code final-squash-instFmt &&
377 git cat-file blob HEAD^:file1 >actual &&
378 test_cmp expect actual &&
379 git cat-file commit HEAD^ >commit &&
380 ! grep "squash" commit &&
381 grep first commit >actual &&
382 test_line_count = 3 actual
385 test_expect_success
'autosquash with empty custom instructionFormat' '
386 git reset --hard base &&
387 test_commit empty-instructionFormat-test &&
389 set_cat_todo_editor &&
390 test_must_fail git -c rebase.instructionFormat= \
391 rebase --autosquash --force-rebase -i HEAD^ >actual &&
392 git log -1 --format="pick %h %s" >expect &&
393 test_cmp expect actual
397 set_backup_editor
() {
398 write_script backup-editor.sh
<<-\EOF
399 cp "$1" .git/backup-"$(basename "$1")"
401 test_set_editor "$PWD/backup-editor.sh"
404 test_expect_success 'autosquash with multiple empty patches' '
406 git commit --allow-empty -m "empty" &&
408 git commit --allow-empty -m "empty2" &&
412 git commit --fixup HEAD^^ &&
415 GIT_USE_REBASE_HELPER=false \
416 git rebase -i --force-rebase --autosquash HEAD~4 &&
417 grep empty2 .git/backup-git-rebase-todo
421 test_expect_success 'extra spaces after fixup!' '
422 base=$(git rev-parse HEAD) &&
423 test_commit to-fixup &&
424 git commit --allow-empty -m "fixup! to-fixup" &&
425 git rebase -i --autosquash --keep-empty HEAD~2 &&
426 parent=$(git rev-parse HEAD^) &&
430 test_expect_success 'wrapped original subject' '
431 if test -d .git/rebase-merge; then git rebase --abort; fi &&
432 base=$(git rev-parse HEAD) &&
433 echo "wrapped subject" >wrapped &&
436 git commit --allow-empty -m "$(printf "To\nfixup")" &&
438 git commit --allow-empty -m "fixup! To fixup" &&
439 git rebase -i --autosquash --keep-empty HEAD~2 &&
440 parent=$(git rev-parse HEAD^) &&
444 test_expect_success 'abort last squash' '
445 test_when_finished "test_might_fail git rebase --abort" &&
446 test_when_finished "git checkout main" &&
448 git checkout -b some-squashes &&
449 git commit --allow-empty -m first &&
450 git commit --allow-empty --squash HEAD &&
451 git commit --allow-empty -m second &&
452 git commit --allow-empty --squash HEAD &&
454 test_must_fail git -c core.editor="grep -q ^pick" \
455 rebase -ki --autosquash HEAD~4 &&
456 : do not finish the squash, but resolve it manually &&
457 git commit --allow-empty --amend -m edited-first &&
463 test_expect_success 'fixup a fixup' '
464 echo 0to-fixup >file0 &&
466 git commit -m "to-fixup" file0 &&
468 git commit --squash HEAD -m X --allow-empty &&
470 git commit --squash HEAD^ -m Y --allow-empty &&
472 git commit -m "squash! $(git rev-parse HEAD^)" -m Z --allow-empty &&
474 git commit -m "squash! $(git rev-parse HEAD^^)" -m W --allow-empty &&
475 git rebase -ki --autosquash HEAD~5 &&
476 test XZWY = $(git show | tr -cd W-Z)
479 test_expect_success 'fixup does not clean up commit message' '
481 git commit --allow-empty -m "$oneline" &&
482 git commit --fixup HEAD --allow-empty &&
483 git -c commit.cleanup=strip rebase -ki --autosquash HEAD~2 &&
484 test "$oneline" = "$(git show -s --format=%s)"