t/README: add missing value for GIT_TEST_DEFAULT_REF_FORMAT
[git/gitster.git] / t / t3415-rebase-autosquash.sh
blob22452ff84cb339936cf2efcb1b4147655943eeff
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_PASSES_SANITIZE_LEAK=true
9 . ./test-lib.sh
11 . "$TEST_DIRECTORY"/lib-rebase.sh
13 test_expect_success setup '
14 echo 0 >file0 &&
15 git add . &&
16 test_tick &&
17 git commit -m "initial commit" &&
18 echo 0 >file1 &&
19 echo 2 >file2 &&
20 git add . &&
21 test_tick &&
22 git commit -m "first commit" &&
23 git tag first-commit &&
24 echo 3 >file3 &&
25 git add . &&
26 test_tick &&
27 git commit -m "second commit" &&
28 git tag base
31 test_auto_fixup () {
32 no_squash= &&
33 if test "x$1" = 'x!'
34 then
35 no_squash=true
36 shift
37 fi &&
39 git reset --hard base &&
40 echo 1 >file1 &&
41 git add -u &&
42 test_tick &&
43 git commit -m "fixup! first" &&
45 git tag $1 &&
46 test_tick &&
47 git rebase $2 HEAD^^^ &&
48 git log --oneline >actual &&
49 if test -n "$no_squash"
50 then
51 test_line_count = 4 actual
52 else
53 test_line_count = 3 actual &&
54 git diff --exit-code $1 &&
55 echo 1 >expect &&
56 git cat-file blob HEAD^:file1 >actual &&
57 test_cmp expect actual &&
58 git cat-file commit HEAD^ >commit &&
59 grep first commit >actual &&
60 test_line_count = 1 actual
64 test_expect_success 'auto fixup (option)' '
65 test_auto_fixup fixup-option --autosquash &&
66 test_auto_fixup fixup-option-i "--autosquash -i"
69 test_expect_success 'auto fixup (config true)' '
70 git config rebase.autosquash true &&
71 test_auto_fixup ! fixup-config-true &&
72 test_auto_fixup fixup-config-true-i -i &&
73 test_auto_fixup ! fixup-config-true-no --no-autosquash &&
74 test_auto_fixup ! fixup-config-true-i-no "-i --no-autosquash"
77 test_expect_success 'auto fixup (config false)' '
78 git config rebase.autosquash false &&
79 test_auto_fixup ! fixup-config-false &&
80 test_auto_fixup ! fixup-config-false-i -i &&
81 test_auto_fixup fixup-config-false-yes --autosquash &&
82 test_auto_fixup fixup-config-false-i-yes "-i --autosquash"
85 test_auto_squash () {
86 no_squash= &&
87 if test "x$1" = 'x!'
88 then
89 no_squash=true
90 shift
91 fi &&
93 git reset --hard base &&
94 echo 1 >file1 &&
95 git add -u &&
96 test_tick &&
97 git commit -m "squash! first" -m "extra para for first" &&
98 git tag $1 &&
99 test_tick &&
100 git rebase $2 HEAD^^^ &&
101 git log --oneline >actual &&
102 if test -n "$no_squash"
103 then
104 test_line_count = 4 actual
105 else
106 test_line_count = 3 actual &&
107 git diff --exit-code $1 &&
108 echo 1 >expect &&
109 git cat-file blob HEAD^:file1 >actual &&
110 test_cmp expect actual &&
111 git cat-file commit HEAD^ >commit &&
112 grep first commit >actual &&
113 test_line_count = 2 actual
117 test_expect_success 'auto squash (option)' '
118 test_auto_squash squash-option --autosquash &&
119 test_auto_squash squash-option-i "--autosquash -i"
122 test_expect_success 'auto squash (config true)' '
123 git config rebase.autosquash true &&
124 test_auto_squash ! squash-config-true &&
125 test_auto_squash squash-config-true-i -i &&
126 test_auto_squash ! squash-config-true-no --no-autosquash &&
127 test_auto_squash ! squash-config-true-i-no "-i --no-autosquash"
130 test_expect_success 'auto squash (config false)' '
131 git config rebase.autosquash false &&
132 test_auto_squash ! squash-config-false &&
133 test_auto_squash ! squash-config-false-i -i &&
134 test_auto_squash squash-config-false-yes --autosquash &&
135 test_auto_squash squash-config-false-i-yes "-i --autosquash"
138 test_expect_success 'misspelled auto squash' '
139 git reset --hard base &&
140 echo 1 >file1 &&
141 git add -u &&
142 test_tick &&
143 git commit -m "squash! forst" &&
144 git tag final-missquash &&
145 test_tick &&
146 git rebase --autosquash -i HEAD^^^ &&
147 git log --oneline >actual &&
148 test_line_count = 4 actual &&
149 git diff --exit-code final-missquash &&
150 git rev-list final-missquash...HEAD >list &&
151 test_must_be_empty list
154 test_expect_success 'auto squash that matches 2 commits' '
155 git reset --hard base &&
156 echo 4 >file4 &&
157 git add file4 &&
158 test_tick &&
159 git commit -m "first new commit" &&
160 echo 1 >file1 &&
161 git add -u &&
162 test_tick &&
163 git commit -m "squash! first" -m "extra para for first" &&
164 git tag final-multisquash &&
165 test_tick &&
166 git rebase --autosquash -i HEAD~4 &&
167 git log --oneline >actual &&
168 test_line_count = 4 actual &&
169 git diff --exit-code final-multisquash &&
170 echo 1 >expect &&
171 git cat-file blob HEAD^^:file1 >actual &&
172 test_cmp expect actual &&
173 git cat-file commit HEAD^^ >commit &&
174 grep first commit >actual &&
175 test_line_count = 2 actual &&
176 git cat-file commit HEAD >commit &&
177 grep first commit >actual &&
178 test_line_count = 1 actual
181 test_expect_success 'auto squash that matches a commit after the squash' '
182 git reset --hard base &&
183 echo 1 >file1 &&
184 git add -u &&
185 test_tick &&
186 git commit -m "squash! third" &&
187 echo 4 >file4 &&
188 git add file4 &&
189 test_tick &&
190 git commit -m "third commit" &&
191 git tag final-presquash &&
192 test_tick &&
193 git rebase --autosquash -i HEAD~4 &&
194 git log --oneline >actual &&
195 test_line_count = 5 actual &&
196 git diff --exit-code final-presquash &&
197 echo 0 >expect &&
198 git cat-file blob HEAD^^:file1 >actual &&
199 test_cmp expect actual &&
200 echo 1 >expect &&
201 git cat-file blob HEAD^:file1 >actual &&
202 test_cmp expect actual &&
203 git cat-file commit HEAD >commit &&
204 grep third commit >actual &&
205 test_line_count = 1 actual &&
206 git cat-file commit HEAD^ >commit &&
207 grep third commit >actual &&
208 test_line_count = 1 actual
210 test_expect_success 'auto squash that matches a sha1' '
211 git reset --hard base &&
212 echo 1 >file1 &&
213 git add -u &&
214 test_tick &&
215 oid=$(git rev-parse --short HEAD^) &&
216 git commit -m "squash! $oid" -m "extra para" &&
217 git tag final-shasquash &&
218 test_tick &&
219 git rebase --autosquash -i HEAD^^^ &&
220 git log --oneline >actual &&
221 test_line_count = 3 actual &&
222 git diff --exit-code final-shasquash &&
223 echo 1 >expect &&
224 git cat-file blob HEAD^:file1 >actual &&
225 test_cmp expect actual &&
226 git cat-file commit HEAD^ >commit &&
227 ! grep "squash" commit &&
228 grep "^extra para" commit >actual &&
229 test_line_count = 1 actual
232 test_expect_success 'auto squash that matches longer sha1' '
233 git reset --hard base &&
234 echo 1 >file1 &&
235 git add -u &&
236 test_tick &&
237 oid=$(git rev-parse --short=11 HEAD^) &&
238 git commit -m "squash! $oid" -m "extra para" &&
239 git tag final-longshasquash &&
240 test_tick &&
241 git rebase --autosquash -i HEAD^^^ &&
242 git log --oneline >actual &&
243 test_line_count = 3 actual &&
244 git diff --exit-code final-longshasquash &&
245 echo 1 >expect &&
246 git cat-file blob HEAD^:file1 >actual &&
247 test_cmp expect actual &&
248 git cat-file commit HEAD^ >commit &&
249 ! grep "squash" commit &&
250 grep "^extra para" commit >actual &&
251 test_line_count = 1 actual
254 test_expect_success 'auto squash of fixup commit that matches branch name which points back to fixup commit' '
255 git reset --hard base &&
256 git commit --allow-empty -m "fixup! self-cycle" &&
257 git branch self-cycle &&
258 GIT_SEQUENCE_EDITOR="cat >tmp" git rebase --autosquash -i HEAD^^ &&
259 sed -ne "/^[^#]/{s/[0-9a-f]\{7,\}/HASH/g;p;}" tmp >actual &&
260 cat <<-EOF >expect &&
261 pick HASH second commit
262 pick HASH fixup! self-cycle # empty
264 test_cmp expect actual
267 test_auto_commit_flags () {
268 git reset --hard base &&
269 echo 1 >file1 &&
270 git add -u &&
271 test_tick &&
272 git commit --$1 first-commit -m "extra para for first" &&
273 git tag final-commit-$1 &&
274 test_tick &&
275 git rebase --autosquash -i HEAD^^^ &&
276 git log --oneline >actual &&
277 test_line_count = 3 actual &&
278 git diff --exit-code final-commit-$1 &&
279 echo 1 >expect &&
280 git cat-file blob HEAD^:file1 >actual &&
281 test_cmp expect actual &&
282 git cat-file commit HEAD^ >commit &&
283 grep first commit >actual &&
284 test_line_count = $2 actual
287 test_expect_success 'use commit --fixup' '
288 test_auto_commit_flags fixup 1
291 test_expect_success 'use commit --squash' '
292 test_auto_commit_flags squash 2
295 test_auto_fixup_fixup () {
296 git reset --hard base &&
297 echo 1 >file1 &&
298 git add -u &&
299 test_tick &&
300 git commit -m "$1! first" -m "extra para for first" &&
301 echo 2 >file1 &&
302 git add -u &&
303 test_tick &&
304 git commit -m "$1! $2! first" -m "second extra para for first" &&
305 git tag "final-$1-$2" &&
306 test_tick &&
308 set_cat_todo_editor &&
309 test_must_fail git rebase --autosquash -i HEAD^^^^ >actual &&
310 head=$(git rev-parse --short HEAD) &&
311 parent1=$(git rev-parse --short HEAD^) &&
312 parent2=$(git rev-parse --short HEAD^^) &&
313 parent3=$(git rev-parse --short HEAD^^^) &&
314 cat >expected <<-EOF &&
315 pick $parent3 first commit
316 $1 $parent1 $1! first
317 $1 $head $1! $2! first
318 pick $parent2 second commit
320 test_cmp expected actual
321 ) &&
322 git rebase --autosquash -i HEAD^^^^ &&
323 git log --oneline >actual &&
324 test_line_count = 3 actual
325 git diff --exit-code "final-$1-$2" &&
326 echo 2 >expect &&
327 git cat-file blob HEAD^:file1 >actual &&
328 test_cmp expect actual &&
329 git cat-file commit HEAD^ >commit &&
330 grep first commit >actual &&
331 if test "$1" = "fixup"
332 then
333 test_line_count = 1 actual
334 elif test "$1" = "squash"
335 then
336 test_line_count = 3 actual
337 else
338 false
342 test_expect_success 'fixup! fixup!' '
343 test_auto_fixup_fixup fixup fixup
346 test_expect_success 'fixup! squash!' '
347 test_auto_fixup_fixup fixup squash
350 test_expect_success 'squash! squash!' '
351 test_auto_fixup_fixup squash squash
354 test_expect_success 'squash! fixup!' '
355 test_auto_fixup_fixup squash fixup
358 test_expect_success 'autosquash with custom inst format' '
359 git reset --hard base &&
360 git config --add rebase.instructionFormat "[%an @ %ar] %s" &&
361 echo 2 >file1 &&
362 git add -u &&
363 test_tick &&
364 oid=$(git rev-parse --short HEAD^) &&
365 git commit -m "squash! $oid" -m "extra para for first" &&
366 echo 1 >file1 &&
367 git add -u &&
368 test_tick &&
369 subject=$(git log -n 1 --format=%s HEAD~2) &&
370 git commit -m "squash! $subject" -m "second extra para for first" &&
371 git tag final-squash-instFmt &&
372 test_tick &&
373 git rebase --autosquash -i HEAD~4 &&
374 git log --oneline >actual &&
375 test_line_count = 3 actual &&
376 git diff --exit-code final-squash-instFmt &&
377 echo 1 >expect &&
378 git cat-file blob HEAD^:file1 >actual &&
379 test_cmp expect actual &&
380 git cat-file commit HEAD^ >commit &&
381 ! grep "squash" commit &&
382 grep first commit >actual &&
383 test_line_count = 3 actual
386 test_expect_success 'autosquash with empty custom instructionFormat' '
387 git reset --hard base &&
388 test_commit empty-instructionFormat-test &&
390 set_cat_todo_editor &&
391 test_must_fail git -c rebase.instructionFormat= \
392 rebase --autosquash --force-rebase -i HEAD^ >actual &&
393 git log -1 --format="pick %h %s" >expect &&
394 test_cmp expect actual
398 set_backup_editor () {
399 write_script backup-editor.sh <<-\EOF
400 cp "$1" .git/backup-"$(basename "$1")"
402 test_set_editor "$PWD/backup-editor.sh"
405 test_expect_success 'autosquash with multiple empty patches' '
406 test_tick &&
407 git commit --allow-empty -m "empty" &&
408 test_tick &&
409 git commit --allow-empty -m "empty2" &&
410 test_tick &&
411 >fixup &&
412 git add fixup &&
413 git commit --fixup HEAD^^ &&
415 set_backup_editor &&
416 GIT_USE_REBASE_HELPER=false \
417 git rebase -i --force-rebase --autosquash HEAD~4 &&
418 grep empty2 .git/backup-git-rebase-todo
422 test_expect_success 'extra spaces after fixup!' '
423 base=$(git rev-parse HEAD) &&
424 test_commit to-fixup &&
425 git commit --allow-empty -m "fixup! to-fixup" &&
426 git rebase -i --autosquash --keep-empty HEAD~2 &&
427 parent=$(git rev-parse HEAD^) &&
428 test $base = $parent
431 test_expect_success 'wrapped original subject' '
432 if test -d .git/rebase-merge; then git rebase --abort; fi &&
433 base=$(git rev-parse HEAD) &&
434 echo "wrapped subject" >wrapped &&
435 git add wrapped &&
436 test_tick &&
437 git commit --allow-empty -m "$(printf "To\nfixup")" &&
438 test_tick &&
439 git commit --allow-empty -m "fixup! To fixup" &&
440 git rebase -i --autosquash --keep-empty HEAD~2 &&
441 parent=$(git rev-parse HEAD^) &&
442 test $base = $parent
445 test_expect_success 'abort last squash' '
446 test_when_finished "test_might_fail git rebase --abort" &&
447 test_when_finished "git checkout main" &&
449 git checkout -b some-squashes &&
450 git commit --allow-empty -m first &&
451 git commit --allow-empty --squash HEAD &&
452 git commit --allow-empty -m second &&
453 git commit --allow-empty --squash HEAD &&
455 test_must_fail git -c core.editor="grep -q ^pick" \
456 rebase -ki --autosquash HEAD~4 &&
457 : do not finish the squash, but resolve it manually &&
458 git commit --allow-empty --amend -m edited-first &&
459 git rebase --skip &&
460 git show >actual &&
461 ! grep first actual
464 test_expect_success 'fixup a fixup' '
465 echo 0to-fixup >file0 &&
466 test_tick &&
467 git commit -m "to-fixup" file0 &&
468 test_tick &&
469 git commit --squash HEAD -m X --allow-empty &&
470 test_tick &&
471 git commit --squash HEAD^ -m Y --allow-empty &&
472 test_tick &&
473 git commit -m "squash! $(git rev-parse HEAD^)" -m Z --allow-empty &&
474 test_tick &&
475 git commit -m "squash! $(git rev-parse HEAD^^)" -m W --allow-empty &&
476 git rebase -ki --autosquash HEAD~5 &&
477 test XZWY = $(git show | tr -cd W-Z)
480 test_expect_success 'fixup does not clean up commit message' '
481 oneline="#818" &&
482 git commit --allow-empty -m "$oneline" &&
483 git commit --fixup HEAD --allow-empty &&
484 git -c commit.cleanup=strip rebase -ki --autosquash HEAD~2 &&
485 test "$oneline" = "$(git show -s --format=%s)"
488 test_done