Merge branch 'fc/fetch-with-import-fix'
[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         git reset --hard base &&
29         echo 1 >file1 &&
30         git add -u &&
31         test_tick &&
32         git commit -m "fixup! first" &&
33
34         git tag $1 &&
35         test_tick &&
36         git rebase $2 -i HEAD^^^ &&
37         git log --oneline >actual &&
38         test_line_count = 3 actual &&
39         git diff --exit-code $1 &&
40         test 1 = "$(git cat-file blob HEAD^:file1)" &&
41         test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
42 }
43
44 test_expect_success 'auto fixup (option)' '
45         test_auto_fixup final-fixup-option --autosquash
46 '
47
48 test_expect_success 'auto fixup (config)' '
49         git config rebase.autosquash true &&
50         test_auto_fixup final-fixup-config-true &&
51         test_must_fail test_auto_fixup fixup-config-true-no --no-autosquash &&
52         git config rebase.autosquash false &&
53         test_must_fail test_auto_fixup final-fixup-config-false
54 '
55
56 test_auto_squash () {
57         git reset --hard base &&
58         echo 1 >file1 &&
59         git add -u &&
60         test_tick &&
61         git commit -m "squash! first" &&
62
63         git tag $1 &&
64         test_tick &&
65         git rebase $2 -i HEAD^^^ &&
66         git log --oneline >actual &&
67         test_line_count = 3 actual &&
68         git diff --exit-code $1 &&
69         test 1 = "$(git cat-file blob HEAD^:file1)" &&
70         test 2 = $(git cat-file commit HEAD^ | grep first | wc -l)
71 }
72
73 test_expect_success 'auto squash (option)' '
74         test_auto_squash final-squash --autosquash
75 '
76
77 test_expect_success 'auto squash (config)' '
78         git config rebase.autosquash true &&
79         test_auto_squash final-squash-config-true &&
80         test_must_fail test_auto_squash squash-config-true-no --no-autosquash &&
81         git config rebase.autosquash false &&
82         test_must_fail test_auto_squash final-squash-config-false
83 '
84
85 test_expect_success 'misspelled auto squash' '
86         git reset --hard base &&
87         echo 1 >file1 &&
88         git add -u &&
89         test_tick &&
90         git commit -m "squash! forst" &&
91         git tag final-missquash &&
92         test_tick &&
93         git rebase --autosquash -i HEAD^^^ &&
94         git log --oneline >actual &&
95         test_line_count = 4 actual &&
96         git diff --exit-code final-missquash &&
97         test 0 = $(git rev-list final-missquash...HEAD | wc -l)
98 '
99
100 test_expect_success 'auto squash that matches 2 commits' '
101         git reset --hard base &&
102         echo 4 >file4 &&
103         git add file4 &&
104         test_tick &&
105         git commit -m "first new commit" &&
106         echo 1 >file1 &&
107         git add -u &&
108         test_tick &&
109         git commit -m "squash! first" &&
110         git tag final-multisquash &&
111         test_tick &&
112         git rebase --autosquash -i HEAD~4 &&
113         git log --oneline >actual &&
114         test_line_count = 4 actual &&
115         git diff --exit-code final-multisquash &&
116         test 1 = "$(git cat-file blob HEAD^^:file1)" &&
117         test 2 = $(git cat-file commit HEAD^^ | grep first | wc -l) &&
118         test 1 = $(git cat-file commit HEAD | grep first | wc -l)
119 '
120
121 test_expect_success 'auto squash that matches a commit after the squash' '
122         git reset --hard base &&
123         echo 1 >file1 &&
124         git add -u &&
125         test_tick &&
126         git commit -m "squash! third" &&
127         echo 4 >file4 &&
128         git add file4 &&
129         test_tick &&
130         git commit -m "third commit" &&
131         git tag final-presquash &&
132         test_tick &&
133         git rebase --autosquash -i HEAD~4 &&
134         git log --oneline >actual &&
135         test_line_count = 5 actual &&
136         git diff --exit-code final-presquash &&
137         test 0 = "$(git cat-file blob HEAD^^:file1)" &&
138         test 1 = "$(git cat-file blob HEAD^:file1)" &&
139         test 1 = $(git cat-file commit HEAD | grep third | wc -l) &&
140         test 1 = $(git cat-file commit HEAD^ | grep third | wc -l)
141 '
142 test_expect_success 'auto squash that matches a sha1' '
143         git reset --hard base &&
144         echo 1 >file1 &&
145         git add -u &&
146         test_tick &&
147         git commit -m "squash! $(git rev-parse --short HEAD^)" &&
148         git tag final-shasquash &&
149         test_tick &&
150         git rebase --autosquash -i HEAD^^^ &&
151         git log --oneline >actual &&
152         test_line_count = 3 actual &&
153         git diff --exit-code final-shasquash &&
154         test 1 = "$(git cat-file blob HEAD^:file1)" &&
155         test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
156 '
157
158 test_expect_success 'auto squash that matches longer sha1' '
159         git reset --hard base &&
160         echo 1 >file1 &&
161         git add -u &&
162         test_tick &&
163         git commit -m "squash! $(git rev-parse --short=11 HEAD^)" &&
164         git tag final-longshasquash &&
165         test_tick &&
166         git rebase --autosquash -i HEAD^^^ &&
167         git log --oneline >actual &&
168         test_line_count = 3 actual &&
169         git diff --exit-code final-longshasquash &&
170         test 1 = "$(git cat-file blob HEAD^:file1)" &&
171         test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
172 '
173
174 test_auto_commit_flags () {
175         git reset --hard base &&
176         echo 1 >file1 &&
177         git add -u &&
178         test_tick &&
179         git commit --$1 first-commit &&
180         git tag final-commit-$1 &&
181         test_tick &&
182         git rebase --autosquash -i HEAD^^^ &&
183         git log --oneline >actual &&
184         test_line_count = 3 actual &&
185         git diff --exit-code final-commit-$1 &&
186         test 1 = "$(git cat-file blob HEAD^:file1)" &&
187         test $2 = $(git cat-file commit HEAD^ | grep first | wc -l)
188 }
189
190 test_expect_success 'use commit --fixup' '
191         test_auto_commit_flags fixup 1
192 '
193
194 test_expect_success 'use commit --squash' '
195         test_auto_commit_flags squash 2
196 '
197
198 test_auto_fixup_fixup () {
199         git reset --hard base &&
200         echo 1 >file1 &&
201         git add -u &&
202         test_tick &&
203         git commit -m "$1! first" &&
204         echo 2 >file1 &&
205         git add -u &&
206         test_tick &&
207         git commit -m "$1! $2! first" &&
208         git tag "final-$1-$2" &&
209         test_tick &&
210         (
211                 set_cat_todo_editor &&
212                 test_must_fail git rebase --autosquash -i HEAD^^^^ >actual &&
213                 cat >expected <<-EOF &&
214                 pick $(git rev-parse --short HEAD^^^) first commit
215                 $1 $(git rev-parse --short HEAD^) $1! first
216                 $1 $(git rev-parse --short HEAD) $1! $2! first
217                 pick $(git rev-parse --short HEAD^^) second commit
218                 EOF
219                 test_cmp expected actual
220         ) &&
221         git rebase --autosquash -i HEAD^^^^ &&
222         git log --oneline >actual &&
223         test_line_count = 3 actual
224         git diff --exit-code "final-$1-$2" &&
225         test 2 = "$(git cat-file blob HEAD^:file1)" &&
226         if test "$1" = "fixup"
227         then
228                 test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
229         elif test "$1" = "squash"
230         then
231                 test 3 = $(git cat-file commit HEAD^ | grep first | wc -l)
232         else
233                 false
234         fi
235 }
236
237 test_expect_success C_LOCALE_OUTPUT 'fixup! fixup!' '
238         test_auto_fixup_fixup fixup fixup
239 '
240
241 test_expect_success C_LOCALE_OUTPUT 'fixup! squash!' '
242         test_auto_fixup_fixup fixup squash
243 '
244
245 test_expect_success C_LOCALE_OUTPUT 'squash! squash!' '
246         test_auto_fixup_fixup squash squash
247 '
248
249 test_expect_success C_LOCALE_OUTPUT 'squash! fixup!' '
250         test_auto_fixup_fixup squash fixup
251 '
252
253 test_expect_success C_LOCALE_OUTPUT 'autosquash with custom inst format' '
254         git reset --hard base &&
255         git config --add rebase.instructionFormat "[%an @ %ar] %s"  &&
256         echo 2 >file1 &&
257         git add -u &&
258         test_tick &&
259         git commit -m "squash! $(git rev-parse --short HEAD^)" &&
260         echo 1 >file1 &&
261         git add -u &&
262         test_tick &&
263         git commit -m "squash! $(git log -n 1 --format=%s HEAD~2)" &&
264         git tag final-squash-instFmt &&
265         test_tick &&
266         git rebase --autosquash -i HEAD~4 &&
267         git log --oneline >actual &&
268         test_line_count = 3 actual &&
269         git diff --exit-code final-squash-instFmt &&
270         test 1 = "$(git cat-file blob HEAD^:file1)" &&
271         test 2 = $(git cat-file commit HEAD^ | grep squash | wc -l)
272 '
273
274 test_expect_success 'autosquash with empty custom instructionFormat' '
275         git reset --hard base &&
276         test_commit empty-instructionFormat-test &&
277         (
278                 set_cat_todo_editor &&
279                 test_must_fail git -c rebase.instructionFormat= \
280                         rebase --autosquash  --force-rebase -i HEAD^ >actual &&
281                 git log -1 --format="pick %h %s" >expect &&
282                 test_cmp expect actual
283         )
284 '
285
286 set_backup_editor () {
287         write_script backup-editor.sh <<-\EOF
288         cp "$1" .git/backup-"$(basename "$1")"
289         EOF
290         test_set_editor "$PWD/backup-editor.sh"
291 }
292
293 test_expect_success 'autosquash with multiple empty patches' '
294         test_tick &&
295         git commit --allow-empty -m "empty" &&
296         test_tick &&
297         git commit --allow-empty -m "empty2" &&
298         test_tick &&
299         >fixup &&
300         git add fixup &&
301         git commit --fixup HEAD^^ &&
302         (
303                 set_backup_editor &&
304                 GIT_USE_REBASE_HELPER=false \
305                 git rebase -i --force-rebase --autosquash HEAD~4 &&
306                 grep empty2 .git/backup-git-rebase-todo
307         )
308 '
309
310 test_expect_success 'extra spaces after fixup!' '
311         base=$(git rev-parse HEAD) &&
312         test_commit to-fixup &&
313         git commit --allow-empty -m "fixup!  to-fixup" &&
314         git rebase -i --autosquash --keep-empty HEAD~2 &&
315         parent=$(git rev-parse HEAD^) &&
316         test $base = $parent
317 '
318
319 test_expect_success 'wrapped original subject' '
320         if test -d .git/rebase-merge; then git rebase --abort; fi &&
321         base=$(git rev-parse HEAD) &&
322         echo "wrapped subject" >wrapped &&
323         git add wrapped &&
324         test_tick &&
325         git commit --allow-empty -m "$(printf "To\nfixup")" &&
326         test_tick &&
327         git commit --allow-empty -m "fixup! To fixup" &&
328         git rebase -i --autosquash --keep-empty HEAD~2 &&
329         parent=$(git rev-parse HEAD^) &&
330         test $base = $parent
331 '
332
333 test_expect_success 'abort last squash' '
334         test_when_finished "test_might_fail git rebase --abort" &&
335         test_when_finished "git checkout master" &&
336
337         git checkout -b some-squashes &&
338         git commit --allow-empty -m first &&
339         git commit --allow-empty --squash HEAD &&
340         git commit --allow-empty -m second &&
341         git commit --allow-empty --squash HEAD &&
342
343         test_must_fail git -c core.editor="grep -q ^pick" \
344                 rebase -ki --autosquash HEAD~4 &&
345         : do not finish the squash, but resolve it manually &&
346         git commit --allow-empty --amend -m edited-first &&
347         git rebase --skip &&
348         git show >actual &&
349         ! grep first actual
350 '
351
352 test_done