t/t3437: fixup here-docs in the 'setup' test
[git] / t / t3415-rebase-autosquash.sh
1 #!/bin/sh
2
3 test_description='auto squash'
4
5 . ./test-lib.sh
6
7 . "$TEST_DIRECTORY"/lib-rebase.sh
8
9 test_expect_success setup '
10         echo 0 >file0 &&
11         git add . &&
12         test_tick &&
13         git commit -m "initial commit" &&
14         echo 0 >file1 &&
15         echo 2 >file2 &&
16         git add . &&
17         test_tick &&
18         git commit -m "first commit" &&
19         git tag first-commit &&
20         echo 3 >file3 &&
21         git add . &&
22         test_tick &&
23         git commit -m "second commit" &&
24         git tag base
25 '
26
27 test_auto_fixup () {
28         no_squash= &&
29         if test "x$1" = 'x!'
30         then
31                 no_squash=true
32                 shift
33         fi &&
34
35         git reset --hard base &&
36         echo 1 >file1 &&
37         git add -u &&
38         test_tick &&
39         git commit -m "fixup! first" &&
40
41         git tag $1 &&
42         test_tick &&
43         git rebase $2 -i HEAD^^^ &&
44         git log --oneline >actual &&
45         if test -n "$no_squash"
46         then
47                 test_line_count = 4 actual
48         else
49                 test_line_count = 3 actual &&
50                 git diff --exit-code $1 &&
51                 echo 1 >expect &&
52                 git cat-file blob HEAD^:file1 >actual &&
53                 test_cmp expect actual &&
54                 git cat-file commit HEAD^ >commit &&
55                 grep first commit >actual &&
56                 test_line_count = 1 actual
57         fi
58 }
59
60 test_expect_success 'auto fixup (option)' '
61         test_auto_fixup final-fixup-option --autosquash
62 '
63
64 test_expect_success 'auto fixup (config)' '
65         git config rebase.autosquash true &&
66         test_auto_fixup final-fixup-config-true &&
67         test_auto_fixup ! fixup-config-true-no --no-autosquash &&
68         git config rebase.autosquash false &&
69         test_auto_fixup ! final-fixup-config-false
70 '
71
72 test_auto_squash () {
73         no_squash= &&
74         if test "x$1" = 'x!'
75         then
76                 no_squash=true
77                 shift
78         fi &&
79
80         git reset --hard base &&
81         echo 1 >file1 &&
82         git add -u &&
83         test_tick &&
84         git commit -m "squash! first" -m "extra para for first" &&
85         git tag $1 &&
86         test_tick &&
87         git rebase $2 -i HEAD^^^ &&
88         git log --oneline >actual &&
89         if test -n "$no_squash"
90         then
91                 test_line_count = 4 actual
92         else
93                 test_line_count = 3 actual &&
94                 git diff --exit-code $1 &&
95                 echo 1 >expect &&
96                 git cat-file blob HEAD^:file1 >actual &&
97                 test_cmp expect actual &&
98                 git cat-file commit HEAD^ >commit &&
99                 grep first commit >actual &&
100                 test_line_count = 2 actual
101         fi
102 }
103
104 test_expect_success 'auto squash (option)' '
105         test_auto_squash final-squash --autosquash
106 '
107
108 test_expect_success 'auto squash (config)' '
109         git config rebase.autosquash true &&
110         test_auto_squash final-squash-config-true &&
111         test_auto_squash ! squash-config-true-no --no-autosquash &&
112         git config rebase.autosquash false &&
113         test_auto_squash ! final-squash-config-false
114 '
115
116 test_expect_success 'misspelled auto squash' '
117         git reset --hard base &&
118         echo 1 >file1 &&
119         git add -u &&
120         test_tick &&
121         git commit -m "squash! forst" &&
122         git tag final-missquash &&
123         test_tick &&
124         git rebase --autosquash -i HEAD^^^ &&
125         git log --oneline >actual &&
126         test_line_count = 4 actual &&
127         git diff --exit-code final-missquash &&
128         git rev-list final-missquash...HEAD >list &&
129         test_must_be_empty list
130 '
131
132 test_expect_success 'auto squash that matches 2 commits' '
133         git reset --hard base &&
134         echo 4 >file4 &&
135         git add file4 &&
136         test_tick &&
137         git commit -m "first new commit" &&
138         echo 1 >file1 &&
139         git add -u &&
140         test_tick &&
141         git commit -m "squash! first" -m "extra para for first" &&
142         git tag final-multisquash &&
143         test_tick &&
144         git rebase --autosquash -i HEAD~4 &&
145         git log --oneline >actual &&
146         test_line_count = 4 actual &&
147         git diff --exit-code final-multisquash &&
148         echo 1 >expect &&
149         git cat-file blob HEAD^^:file1 >actual &&
150         test_cmp expect actual &&
151         git cat-file commit HEAD^^ >commit &&
152         grep first commit >actual &&
153         test_line_count = 2 actual &&
154         git cat-file commit HEAD >commit &&
155         grep first commit >actual &&
156         test_line_count = 1 actual
157 '
158
159 test_expect_success 'auto squash that matches a commit after the squash' '
160         git reset --hard base &&
161         echo 1 >file1 &&
162         git add -u &&
163         test_tick &&
164         git commit -m "squash! third" &&
165         echo 4 >file4 &&
166         git add file4 &&
167         test_tick &&
168         git commit -m "third commit" &&
169         git tag final-presquash &&
170         test_tick &&
171         git rebase --autosquash -i HEAD~4 &&
172         git log --oneline >actual &&
173         test_line_count = 5 actual &&
174         git diff --exit-code final-presquash &&
175         echo 0 >expect &&
176         git cat-file blob HEAD^^:file1 >actual &&
177         test_cmp expect actual &&
178         echo 1 >expect &&
179         git cat-file blob HEAD^:file1 >actual &&
180         test_cmp expect actual &&
181         git cat-file commit HEAD >commit &&
182         grep third commit >actual &&
183         test_line_count = 1 actual &&
184         git cat-file commit HEAD^ >commit &&
185         grep third commit >actual &&
186         test_line_count = 1 actual
187 '
188 test_expect_success 'auto squash that matches a sha1' '
189         git reset --hard base &&
190         echo 1 >file1 &&
191         git add -u &&
192         test_tick &&
193         oid=$(git rev-parse --short HEAD^) &&
194         git commit -m "squash! $oid" -m "extra para" &&
195         git tag final-shasquash &&
196         test_tick &&
197         git rebase --autosquash -i HEAD^^^ &&
198         git log --oneline >actual &&
199         test_line_count = 3 actual &&
200         git diff --exit-code final-shasquash &&
201         echo 1 >expect &&
202         git cat-file blob HEAD^:file1 >actual &&
203         test_cmp expect actual &&
204         git cat-file commit HEAD^ >commit &&
205         ! grep "squash" commit &&
206         grep "^extra para" commit >actual &&
207         test_line_count = 1 actual
208 '
209
210 test_expect_success 'auto squash that matches longer sha1' '
211         git reset --hard base &&
212         echo 1 >file1 &&
213         git add -u &&
214         test_tick &&
215         oid=$(git rev-parse --short=11 HEAD^) &&
216         git commit -m "squash! $oid" -m "extra para" &&
217         git tag final-longshasquash &&
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-longshasquash &&
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
230 '
231
232 test_auto_commit_flags () {
233         git reset --hard base &&
234         echo 1 >file1 &&
235         git add -u &&
236         test_tick &&
237         git commit --$1 first-commit -m "extra para for first" &&
238         git tag final-commit-$1 &&
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-commit-$1 &&
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 first commit >actual &&
249         test_line_count = $2 actual
250 }
251
252 test_expect_success 'use commit --fixup' '
253         test_auto_commit_flags fixup 1
254 '
255
256 test_expect_success 'use commit --squash' '
257         test_auto_commit_flags squash 2
258 '
259
260 test_auto_fixup_fixup () {
261         git reset --hard base &&
262         echo 1 >file1 &&
263         git add -u &&
264         test_tick &&
265         git commit -m "$1! first" -m "extra para for first" &&
266         echo 2 >file1 &&
267         git add -u &&
268         test_tick &&
269         git commit -m "$1! $2! first" -m "second extra para for first" &&
270         git tag "final-$1-$2" &&
271         test_tick &&
272         (
273                 set_cat_todo_editor &&
274                 test_must_fail git rebase --autosquash -i HEAD^^^^ >actual &&
275                 head=$(git rev-parse --short HEAD) &&
276                 parent1=$(git rev-parse --short HEAD^) &&
277                 parent2=$(git rev-parse --short HEAD^^) &&
278                 parent3=$(git rev-parse --short HEAD^^^) &&
279                 cat >expected <<-EOF &&
280                 pick $parent3 first commit
281                 $1 $parent1 $1! first
282                 $1 $head $1! $2! first
283                 pick $parent2 second commit
284                 EOF
285                 test_cmp expected actual
286         ) &&
287         git rebase --autosquash -i HEAD^^^^ &&
288         git log --oneline >actual &&
289         test_line_count = 3 actual
290         git diff --exit-code "final-$1-$2" &&
291         echo 2 >expect &&
292         git cat-file blob HEAD^:file1 >actual &&
293         test_cmp expect actual &&
294         git cat-file commit HEAD^ >commit &&
295         grep first commit >actual &&
296         if test "$1" = "fixup"
297         then
298                 test_line_count = 1 actual
299         elif test "$1" = "squash"
300         then
301                 test_line_count = 3 actual
302         else
303                 false
304         fi
305 }
306
307 test_expect_success C_LOCALE_OUTPUT 'fixup! fixup!' '
308         test_auto_fixup_fixup fixup fixup
309 '
310
311 test_expect_success C_LOCALE_OUTPUT 'fixup! squash!' '
312         test_auto_fixup_fixup fixup squash
313 '
314
315 test_expect_success C_LOCALE_OUTPUT 'squash! squash!' '
316         test_auto_fixup_fixup squash squash
317 '
318
319 test_expect_success C_LOCALE_OUTPUT 'squash! fixup!' '
320         test_auto_fixup_fixup squash fixup
321 '
322
323 test_expect_success C_LOCALE_OUTPUT 'autosquash with custom inst format' '
324         git reset --hard base &&
325         git config --add rebase.instructionFormat "[%an @ %ar] %s"  &&
326         echo 2 >file1 &&
327         git add -u &&
328         test_tick &&
329         oid=$(git rev-parse --short HEAD^) &&
330         git commit -m "squash! $oid" -m "extra para for first" &&
331         echo 1 >file1 &&
332         git add -u &&
333         test_tick &&
334         subject=$(git log -n 1 --format=%s HEAD~2) &&
335         git commit -m "squash! $subject" -m "second extra para for first" &&
336         git tag final-squash-instFmt &&
337         test_tick &&
338         git rebase --autosquash -i HEAD~4 &&
339         git log --oneline >actual &&
340         test_line_count = 3 actual &&
341         git diff --exit-code final-squash-instFmt &&
342         echo 1 >expect &&
343         git cat-file blob HEAD^:file1 >actual &&
344         test_cmp expect actual &&
345         git cat-file commit HEAD^ >commit &&
346         ! grep "squash" commit &&
347         grep first commit >actual &&
348         test_line_count = 3 actual
349 '
350
351 test_expect_success 'autosquash with empty custom instructionFormat' '
352         git reset --hard base &&
353         test_commit empty-instructionFormat-test &&
354         (
355                 set_cat_todo_editor &&
356                 test_must_fail git -c rebase.instructionFormat= \
357                         rebase --autosquash  --force-rebase -i HEAD^ >actual &&
358                 git log -1 --format="pick %h %s" >expect &&
359                 test_cmp expect actual
360         )
361 '
362
363 set_backup_editor () {
364         write_script backup-editor.sh <<-\EOF
365         cp "$1" .git/backup-"$(basename "$1")"
366         EOF
367         test_set_editor "$PWD/backup-editor.sh"
368 }
369
370 test_expect_success 'autosquash with multiple empty patches' '
371         test_tick &&
372         git commit --allow-empty -m "empty" &&
373         test_tick &&
374         git commit --allow-empty -m "empty2" &&
375         test_tick &&
376         >fixup &&
377         git add fixup &&
378         git commit --fixup HEAD^^ &&
379         (
380                 set_backup_editor &&
381                 GIT_USE_REBASE_HELPER=false \
382                 git rebase -i --force-rebase --autosquash HEAD~4 &&
383                 grep empty2 .git/backup-git-rebase-todo
384         )
385 '
386
387 test_expect_success 'extra spaces after fixup!' '
388         base=$(git rev-parse HEAD) &&
389         test_commit to-fixup &&
390         git commit --allow-empty -m "fixup!  to-fixup" &&
391         git rebase -i --autosquash --keep-empty HEAD~2 &&
392         parent=$(git rev-parse HEAD^) &&
393         test $base = $parent
394 '
395
396 test_expect_success 'wrapped original subject' '
397         if test -d .git/rebase-merge; then git rebase --abort; fi &&
398         base=$(git rev-parse HEAD) &&
399         echo "wrapped subject" >wrapped &&
400         git add wrapped &&
401         test_tick &&
402         git commit --allow-empty -m "$(printf "To\nfixup")" &&
403         test_tick &&
404         git commit --allow-empty -m "fixup! To fixup" &&
405         git rebase -i --autosquash --keep-empty HEAD~2 &&
406         parent=$(git rev-parse HEAD^) &&
407         test $base = $parent
408 '
409
410 test_expect_success 'abort last squash' '
411         test_when_finished "test_might_fail git rebase --abort" &&
412         test_when_finished "git checkout master" &&
413
414         git checkout -b some-squashes &&
415         git commit --allow-empty -m first &&
416         git commit --allow-empty --squash HEAD &&
417         git commit --allow-empty -m second &&
418         git commit --allow-empty --squash HEAD &&
419
420         test_must_fail git -c core.editor="grep -q ^pick" \
421                 rebase -ki --autosquash HEAD~4 &&
422         : do not finish the squash, but resolve it manually &&
423         git commit --allow-empty --amend -m edited-first &&
424         git rebase --skip &&
425         git show >actual &&
426         ! grep first actual
427 '
428
429 test_expect_success 'fixup a fixup' '
430         echo 0to-fixup >file0 &&
431         test_tick &&
432         git commit -m "to-fixup" file0 &&
433         test_tick &&
434         git commit --squash HEAD -m X --allow-empty &&
435         test_tick &&
436         git commit --squash HEAD^ -m Y --allow-empty &&
437         test_tick &&
438         git commit -m "squash! $(git rev-parse HEAD^)" -m Z --allow-empty &&
439         test_tick &&
440         git commit -m "squash! $(git rev-parse HEAD^^)" -m W --allow-empty &&
441         git rebase -ki --autosquash HEAD~5 &&
442         test XZWY = $(git show | tr -cd W-Z)
443 '
444
445 test_done