Sync with 2.44.1
[git/gitster.git] / t / t3415-rebase-autosquash.sh
blobfcc40d6fe1fd5b2a9c4f2a5e4ede15e73c247790
1 #!/bin/sh
3 test_description='auto squash'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 . ./test-lib.sh
10 . "$TEST_DIRECTORY"/lib-rebase.sh
12 test_expect_success setup '
13 echo 0 >file0 &&
14 git add . &&
15 test_tick &&
16 git commit -m "initial commit" &&
17 echo 0 >file1 &&
18 echo 2 >file2 &&
19 git add . &&
20 test_tick &&
21 git commit -m "first commit" &&
22 git tag first-commit &&
23 echo 3 >file3 &&
24 git add . &&
25 test_tick &&
26 git commit -m "second commit" &&
27 git tag base
30 test_auto_fixup () {
31 no_squash= &&
32 if test "x$1" = 'x!'
33 then
34 no_squash=true
35 shift
36 fi &&
38 git reset --hard base &&
39 echo 1 >file1 &&
40 git add -u &&
41 test_tick &&
42 git commit -m "fixup! first" &&
44 git tag $1 &&
45 test_tick &&
46 git rebase $2 HEAD^^^ &&
47 git log --oneline >actual &&
48 if test -n "$no_squash"
49 then
50 test_line_count = 4 actual
51 else
52 test_line_count = 3 actual &&
53 git diff --exit-code $1 &&
54 echo 1 >expect &&
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"
84 test_auto_squash () {
85 no_squash= &&
86 if test "x$1" = 'x!'
87 then
88 no_squash=true
89 shift
90 fi &&
92 git reset --hard base &&
93 echo 1 >file1 &&
94 git add -u &&
95 test_tick &&
96 git commit -m "squash! first" -m "extra para for first" &&
97 git tag $1 &&
98 test_tick &&
99 git rebase $2 HEAD^^^ &&
100 git log --oneline >actual &&
101 if test -n "$no_squash"
102 then
103 test_line_count = 4 actual
104 else
105 test_line_count = 3 actual &&
106 git diff --exit-code $1 &&
107 echo 1 >expect &&
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 &&
139 echo 1 >file1 &&
140 git add -u &&
141 test_tick &&
142 git commit -m "squash! forst" &&
143 git tag final-missquash &&
144 test_tick &&
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 &&
155 echo 4 >file4 &&
156 git add file4 &&
157 test_tick &&
158 git commit -m "first new commit" &&
159 echo 1 >file1 &&
160 git add -u &&
161 test_tick &&
162 git commit -m "squash! first" -m "extra para for first" &&
163 git tag final-multisquash &&
164 test_tick &&
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 &&
169 echo 1 >expect &&
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 &&
182 echo 1 >file1 &&
183 git add -u &&
184 test_tick &&
185 git commit -m "squash! third" &&
186 echo 4 >file4 &&
187 git add file4 &&
188 test_tick &&
189 git commit -m "third commit" &&
190 git tag final-presquash &&
191 test_tick &&
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 &&
196 echo 0 >expect &&
197 git cat-file blob HEAD^^:file1 >actual &&
198 test_cmp expect actual &&
199 echo 1 >expect &&
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 &&
211 echo 1 >file1 &&
212 git add -u &&
213 test_tick &&
214 oid=$(git rev-parse --short HEAD^) &&
215 git commit -m "squash! $oid" -m "extra para" &&
216 git tag final-shasquash &&
217 test_tick &&
218 git rebase --autosquash -i HEAD^^^ &&
219 git log --oneline >actual &&
220 test_line_count = 3 actual &&
221 git diff --exit-code final-shasquash &&
222 echo 1 >expect &&
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 &&
233 echo 1 >file1 &&
234 git add -u &&
235 test_tick &&
236 oid=$(git rev-parse --short=11 HEAD^) &&
237 git commit -m "squash! $oid" -m "extra para" &&
238 git tag final-longshasquash &&
239 test_tick &&
240 git rebase --autosquash -i HEAD^^^ &&
241 git log --oneline >actual &&
242 test_line_count = 3 actual &&
243 git diff --exit-code final-longshasquash &&
244 echo 1 >expect &&
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 &&
268 echo 1 >file1 &&
269 git add -u &&
270 test_tick &&
271 git commit --$1 first-commit -m "extra para for first" &&
272 git tag final-commit-$1 &&
273 test_tick &&
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 &&
278 echo 1 >expect &&
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 &&
296 echo 1 >file1 &&
297 git add -u &&
298 test_tick &&
299 git commit -m "$1! first" -m "extra para for first" &&
300 echo 2 >file1 &&
301 git add -u &&
302 test_tick &&
303 git commit -m "$1! $2! first" -m "second extra para for first" &&
304 git tag "final-$1-$2" &&
305 test_tick &&
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
320 ) &&
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" &&
325 echo 2 >expect &&
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"
331 then
332 test_line_count = 1 actual
333 elif test "$1" = "squash"
334 then
335 test_line_count = 3 actual
336 else
337 false
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" &&
360 echo 2 >file1 &&
361 git add -u &&
362 test_tick &&
363 oid=$(git rev-parse --short HEAD^) &&
364 git commit -m "squash! $oid" -m "extra para for first" &&
365 echo 1 >file1 &&
366 git add -u &&
367 test_tick &&
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 &&
371 test_tick &&
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 &&
376 echo 1 >expect &&
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' '
405 test_tick &&
406 git commit --allow-empty -m "empty" &&
407 test_tick &&
408 git commit --allow-empty -m "empty2" &&
409 test_tick &&
410 >fixup &&
411 git add fixup &&
412 git commit --fixup HEAD^^ &&
414 set_backup_editor &&
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^) &&
427 test $base = $parent
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 &&
434 git add wrapped &&
435 test_tick &&
436 git commit --allow-empty -m "$(printf "To\nfixup")" &&
437 test_tick &&
438 git commit --allow-empty -m "fixup! To fixup" &&
439 git rebase -i --autosquash --keep-empty HEAD~2 &&
440 parent=$(git rev-parse HEAD^) &&
441 test $base = $parent
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 &&
458 git rebase --skip &&
459 git show >actual &&
460 ! grep first actual
463 test_expect_success 'fixup a fixup' '
464 echo 0to-fixup >file0 &&
465 test_tick &&
466 git commit -m "to-fixup" file0 &&
467 test_tick &&
468 git commit --squash HEAD -m X --allow-empty &&
469 test_tick &&
470 git commit --squash HEAD^ -m Y --allow-empty &&
471 test_tick &&
472 git commit -m "squash! $(git rev-parse HEAD^)" -m Z --allow-empty &&
473 test_tick &&
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' '
480 oneline="#818" &&
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)"
487 test_done