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 -i 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 final-fixup-option --autosquash
67 test_expect_success 'auto fixup (config)' '
68 git config rebase.autosquash true &&
69 test_auto_fixup final-fixup-config-true &&
70 test_auto_fixup ! fixup-config-true-no --no-autosquash &&
71 git config rebase.autosquash false &&
72 test_auto_fixup ! final-fixup-config-false
83 git reset --hard base &&
87 git commit -m "squash! first" -m "extra para for first" &&
90 git rebase $2 -i HEAD^^^ &&
91 git log --oneline >actual &&
92 if test -n "$no_squash"
94 test_line_count = 4 actual
96 test_line_count = 3 actual &&
97 git diff --exit-code $1 &&
99 git cat-file blob HEAD^:file1 >actual &&
100 test_cmp expect actual &&
101 git cat-file commit HEAD^ >commit &&
102 grep first commit >actual &&
103 test_line_count = 2 actual
107 test_expect_success 'auto squash (option)' '
108 test_auto_squash final-squash --autosquash
111 test_expect_success 'auto squash (config)' '
112 git config rebase.autosquash true &&
113 test_auto_squash final-squash-config-true &&
114 test_auto_squash ! squash-config-true-no --no-autosquash &&
115 git config rebase.autosquash false &&
116 test_auto_squash ! final-squash-config-false
119 test_expect_success 'misspelled auto squash' '
120 git reset --hard base &&
124 git commit -m "squash! forst" &&
125 git tag final-missquash &&
127 git rebase --autosquash -i HEAD^^^ &&
128 git log --oneline >actual &&
129 test_line_count = 4 actual &&
130 git diff --exit-code final-missquash &&
131 git rev-list final-missquash...HEAD >list &&
132 test_must_be_empty list
135 test_expect_success 'auto squash that matches 2 commits' '
136 git reset --hard base &&
140 git commit -m "first new commit" &&
144 git commit -m "squash! first" -m "extra para for first" &&
145 git tag final-multisquash &&
147 git rebase --autosquash -i HEAD~4 &&
148 git log --oneline >actual &&
149 test_line_count = 4 actual &&
150 git diff --exit-code final-multisquash &&
152 git cat-file blob HEAD^^:file1 >actual &&
153 test_cmp expect actual &&
154 git cat-file commit HEAD^^ >commit &&
155 grep first commit >actual &&
156 test_line_count = 2 actual &&
157 git cat-file commit HEAD >commit &&
158 grep first commit >actual &&
159 test_line_count = 1 actual
162 test_expect_success 'auto squash that matches a commit after the squash' '
163 git reset --hard base &&
167 git commit -m "squash! third" &&
171 git commit -m "third commit" &&
172 git tag final-presquash &&
174 git rebase --autosquash -i HEAD~4 &&
175 git log --oneline >actual &&
176 test_line_count = 5 actual &&
177 git diff --exit-code final-presquash &&
179 git cat-file blob HEAD^^:file1 >actual &&
180 test_cmp expect actual &&
182 git cat-file blob HEAD^:file1 >actual &&
183 test_cmp expect actual &&
184 git cat-file commit HEAD >commit &&
185 grep third commit >actual &&
186 test_line_count = 1 actual &&
187 git cat-file commit HEAD^ >commit &&
188 grep third commit >actual &&
189 test_line_count = 1 actual
191 test_expect_success 'auto squash that matches a sha1' '
192 git reset --hard base &&
196 oid=$(git rev-parse --short HEAD^) &&
197 git commit -m "squash! $oid" -m "extra para" &&
198 git tag final-shasquash &&
200 git rebase --autosquash -i HEAD^^^ &&
201 git log --oneline >actual &&
202 test_line_count = 3 actual &&
203 git diff --exit-code final-shasquash &&
205 git cat-file blob HEAD^:file1 >actual &&
206 test_cmp expect actual &&
207 git cat-file commit HEAD^ >commit &&
208 ! grep "squash" commit &&
209 grep "^extra para" commit >actual &&
210 test_line_count = 1 actual
213 test_expect_success 'auto squash that matches longer sha1' '
214 git reset --hard base &&
218 oid=$(git rev-parse --short=11 HEAD^) &&
219 git commit -m "squash! $oid" -m "extra para" &&
220 git tag final-longshasquash &&
222 git rebase --autosquash -i HEAD^^^ &&
223 git log --oneline >actual &&
224 test_line_count = 3 actual &&
225 git diff --exit-code final-longshasquash &&
227 git cat-file blob HEAD^:file1 >actual &&
228 test_cmp expect actual &&
229 git cat-file commit HEAD^ >commit &&
230 ! grep "squash" commit &&
231 grep "^extra para" commit >actual &&
232 test_line_count = 1 actual
235 test_auto_commit_flags () {
236 git reset --hard base &&
240 git commit --$1 first-commit -m "extra para for first" &&
241 git tag final-commit-$1 &&
243 git rebase --autosquash -i HEAD^^^ &&
244 git log --oneline >actual &&
245 test_line_count = 3 actual &&
246 git diff --exit-code final-commit-$1 &&
248 git cat-file blob HEAD^:file1 >actual &&
249 test_cmp expect actual &&
250 git cat-file commit HEAD^ >commit &&
251 grep first commit >actual &&
252 test_line_count = $2 actual
255 test_expect_success 'use commit --fixup' '
256 test_auto_commit_flags fixup 1
259 test_expect_success 'use commit --squash' '
260 test_auto_commit_flags squash 2
263 test_auto_fixup_fixup () {
264 git reset --hard base &&
268 git commit -m "$1! first" -m "extra para for first" &&
272 git commit -m "$1! $2! first" -m "second extra para for first" &&
273 git tag "final-$1-$2" &&
276 set_cat_todo_editor &&
277 test_must_fail git rebase --autosquash -i HEAD^^^^ >actual &&
278 head=$(git rev-parse --short HEAD) &&
279 parent1=$(git rev-parse --short HEAD^) &&
280 parent2=$(git rev-parse --short HEAD^^) &&
281 parent3=$(git rev-parse --short HEAD^^^) &&
282 cat >expected <<-EOF &&
283 pick $parent3 first commit
284 $1 $parent1 $1! first
285 $1 $head $1! $2! first
286 pick $parent2 second commit
288 test_cmp expected actual
290 git rebase --autosquash -i HEAD^^^^ &&
291 git log --oneline >actual &&
292 test_line_count = 3 actual
293 git diff --exit-code "final-$1-$2" &&
295 git cat-file blob HEAD^:file1 >actual &&
296 test_cmp expect actual &&
297 git cat-file commit HEAD^ >commit &&
298 grep first commit >actual &&
299 if test "$1" = "fixup"
301 test_line_count = 1 actual
302 elif test "$1" = "squash"
304 test_line_count = 3 actual
310 test_expect_success 'fixup! fixup!' '
311 test_auto_fixup_fixup fixup fixup
314 test_expect_success 'fixup! squash!' '
315 test_auto_fixup_fixup fixup squash
318 test_expect_success 'squash! squash!' '
319 test_auto_fixup_fixup squash squash
322 test_expect_success 'squash! fixup!' '
323 test_auto_fixup_fixup squash fixup
326 test_expect_success 'autosquash with custom inst format' '
327 git reset --hard base &&
328 git config --add rebase.instructionFormat "[%an @ %ar] %s" &&
332 oid=$(git rev-parse --short HEAD^) &&
333 git commit -m "squash! $oid" -m "extra para for first" &&
337 subject=$(git log -n 1 --format=%s HEAD~2) &&
338 git commit -m "squash! $subject" -m "second extra para for first" &&
339 git tag final-squash-instFmt &&
341 git rebase --autosquash -i HEAD~4 &&
342 git log --oneline >actual &&
343 test_line_count = 3 actual &&
344 git diff --exit-code final-squash-instFmt &&
346 git cat-file blob HEAD^:file1 >actual &&
347 test_cmp expect actual &&
348 git cat-file commit HEAD^ >commit &&
349 ! grep "squash" commit &&
350 grep first commit >actual &&
351 test_line_count = 3 actual
354 test_expect_success 'autosquash with empty custom instructionFormat' '
355 git reset --hard base &&
356 test_commit empty-instructionFormat-test &&
358 set_cat_todo_editor &&
359 test_must_fail git -c rebase.instructionFormat= \
360 rebase --autosquash --force-rebase -i HEAD^ >actual &&
361 git log -1 --format="pick %h %s" >expect &&
362 test_cmp expect actual
366 set_backup_editor () {
367 write_script backup-editor.sh <<-\EOF
368 cp "$1" .git/backup-"$(basename "$1")"
370 test_set_editor "$PWD/backup-editor.sh"
373 test_expect_success 'autosquash with multiple empty patches' '
375 git commit --allow-empty -m "empty" &&
377 git commit --allow-empty -m "empty2" &&
381 git commit --fixup HEAD^^ &&
384 GIT_USE_REBASE_HELPER=false \
385 git rebase -i --force-rebase --autosquash HEAD~4 &&
386 grep empty2 .git/backup-git-rebase-todo
390 test_expect_success 'extra spaces after fixup!' '
391 base=$(git rev-parse HEAD) &&
392 test_commit to-fixup &&
393 git commit --allow-empty -m "fixup! to-fixup" &&
394 git rebase -i --autosquash --keep-empty HEAD~2 &&
395 parent=$(git rev-parse HEAD^) &&
399 test_expect_success 'wrapped original subject' '
400 if test -d .git/rebase-merge; then git rebase --abort; fi &&
401 base=$(git rev-parse HEAD) &&
402 echo "wrapped subject" >wrapped &&
405 git commit --allow-empty -m "$(printf "To\nfixup")" &&
407 git commit --allow-empty -m "fixup! To fixup" &&
408 git rebase -i --autosquash --keep-empty HEAD~2 &&
409 parent=$(git rev-parse HEAD^) &&
413 test_expect_success 'abort last squash' '
414 test_when_finished "test_might_fail git rebase --abort" &&
415 test_when_finished "git checkout main" &&
417 git checkout -b some-squashes &&
418 git commit --allow-empty -m first &&
419 git commit --allow-empty --squash HEAD &&
420 git commit --allow-empty -m second &&
421 git commit --allow-empty --squash HEAD &&
423 test_must_fail git -c core.editor="grep -q ^pick" \
424 rebase -ki --autosquash HEAD~4 &&
425 : do not finish the squash, but resolve it manually &&
426 git commit --allow-empty --amend -m edited-first &&
432 test_expect_success 'fixup a fixup' '
433 echo 0to-fixup >file0 &&
435 git commit -m "to-fixup" file0 &&
437 git commit --squash HEAD -m X --allow-empty &&
439 git commit --squash HEAD^ -m Y --allow-empty &&
441 git commit -m "squash! $(git rev-parse HEAD^)" -m Z --allow-empty &&
443 git commit -m "squash! $(git rev-parse HEAD^^)" -m W --allow-empty &&
444 git rebase -ki --autosquash HEAD~5 &&
445 test XZWY = $(git show | tr -cd W-Z)
448 test_expect_success 'fixup does not clean up commit message' '
450 git commit --allow-empty -m "$oneline" &&
451 git commit --fixup HEAD --allow-empty &&
452 git -c commit.cleanup=strip rebase -ki --autosquash HEAD~2 &&
453 test "$oneline" = "$(git show -s --format=%s)"