Merge branch 'jc/diff-index-quick-exit-early' into maint
[git] / t / t7501-commit.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>
4 #
5
6 # FIXME: Test the various index usages, -i and -o, test reflog,
7 # signoff
8
9 test_description='git commit'
10 . ./test-lib.sh
11
12 test_tick
13
14 test_expect_success \
15         "initial status" \
16         "echo 'bongo bongo' >file &&
17          git add file"
18
19 test_expect_success "Constructing initial commit" '
20         git status >actual &&
21         test_i18ngrep "Initial commit" actual
22 '
23
24 test_expect_success \
25         "fail initial amend" \
26         "test_must_fail git commit --amend"
27
28 test_expect_success \
29         "initial commit" \
30         "git commit -m initial"
31
32 test_expect_success \
33         "invalid options 1" \
34         "test_must_fail git commit -m foo -m bar -F file"
35
36 test_expect_success \
37         "invalid options 2" \
38         "test_must_fail git commit -C HEAD -m illegal"
39
40 test_expect_success \
41         "using paths with -a" \
42         "echo King of the bongo >file &&
43         test_must_fail git commit -m foo -a file"
44
45 test_expect_success PERL 'can use paths with --interactive' '
46         echo bong-o-bong >file &&
47         # 2: update, 1:st path, that is all, 7: quit
48         ( echo 2; echo 1; echo; echo 7 ) |
49         git commit -m foo --interactive file &&
50         git reset --hard HEAD^
51 '
52
53 test_expect_success \
54         "using invalid commit with -C" \
55         "test_must_fail git commit -C bogus"
56
57 test_expect_success \
58         "testing nothing to commit" \
59         "test_must_fail git commit -m initial"
60
61 test_expect_success \
62         "next commit" \
63         "echo 'bongo bongo bongo' >file \
64          git commit -m next -a"
65
66 test_expect_success \
67         "commit message from non-existing file" \
68         "echo 'more bongo: bongo bongo bongo bongo' >file && \
69          test_must_fail git commit -F gah -a"
70
71 # Empty except stray tabs and spaces on a few lines.
72 sed -e 's/@$//' >msg <<EOF
73                 @
74
75   @
76 Signed-off-by: hula
77 EOF
78 test_expect_success \
79         "empty commit message" \
80         "test_must_fail git commit -F msg -a"
81
82 test_expect_success \
83         "commit message from file" \
84         "echo 'this is the commit message, coming from a file' >msg && \
85          git commit -F msg -a"
86
87 cat >editor <<\EOF
88 #!/bin/sh
89 sed -e "s/a file/an amend commit/g" < "$1" > "$1-"
90 mv "$1-" "$1"
91 EOF
92 chmod 755 editor
93
94 test_expect_success \
95         "amend commit" \
96         "EDITOR=./editor git commit --amend"
97
98 test_expect_success \
99         "passing -m and -F" \
100         "echo 'enough with the bongos' >file && \
101          test_must_fail git commit -F msg -m amending ."
102
103 test_expect_success \
104         "using message from other commit" \
105         "git commit -C HEAD^ ."
106
107 cat >editor <<\EOF
108 #!/bin/sh
109 sed -e "s/amend/older/g"  < "$1" > "$1-"
110 mv "$1-" "$1"
111 EOF
112 chmod 755 editor
113
114 test_expect_success \
115         "editing message from other commit" \
116         "echo 'hula hula' >file && \
117          EDITOR=./editor git commit -c HEAD^ -a"
118
119 test_expect_success \
120         "message from stdin" \
121         "echo 'silly new contents' >file && \
122          echo commit message from stdin | git commit -F - -a"
123
124 test_expect_success \
125         "overriding author from command line" \
126         "echo 'gak' >file && \
127          git commit -m 'author' --author 'Rubber Duck <rduck@convoy.org>' -a >output 2>&1"
128
129 test_expect_success \
130         "commit --author output mentions author" \
131         "grep Rubber.Duck output"
132
133 test_expect_success PERL \
134         "interactive add" \
135         "echo 7 | git commit --interactive | grep 'What now'"
136
137 test_expect_success PERL \
138         "commit --interactive doesn't change index if editor aborts" \
139         "echo zoo >file &&
140         test_must_fail git diff --exit-code >diff1 &&
141         (echo u ; echo '*' ; echo q) |
142         (EDITOR=: && export EDITOR &&
143          test_must_fail git commit --interactive) &&
144         git diff >diff2 &&
145         test_cmp diff1 diff2"
146
147 test_expect_success \
148         "showing committed revisions" \
149         "git rev-list HEAD >current"
150
151 cat >editor <<\EOF
152 #!/bin/sh
153 sed -e "s/good/bad/g" < "$1" > "$1-"
154 mv "$1-" "$1"
155 EOF
156 chmod 755 editor
157
158 cat >msg <<EOF
159 A good commit message.
160 EOF
161
162 test_expect_success \
163         'editor not invoked if -F is given' '
164          echo "moo" >file &&
165          EDITOR=./editor git commit -a -F msg &&
166          git show -s --pretty=format:"%s" | grep -q good &&
167          echo "quack" >file &&
168          echo "Another good message." | EDITOR=./editor git commit -a -F - &&
169          git show -s --pretty=format:"%s" | grep -q good
170          '
171 # We could just check the head sha1, but checking each commit makes it
172 # easier to isolate bugs.
173
174 cat >expected <<\EOF
175 72c0dc9855b0c9dadcbfd5a31cab072e0cb774ca
176 9b88fc14ce6b32e3d9ee021531a54f18a5cf38a2
177 3536bbb352c3a1ef9a420f5b4242d48578b92aa7
178 d381ac431806e53f3dd7ac2f1ae0534f36d738b9
179 4fd44095ad6334f3ef72e4c5ec8ddf108174b54a
180 402702b49136e7587daa9280e91e4bb7cb2179f7
181 EOF
182
183 test_expect_success \
184     'validate git rev-list output.' \
185     'test_cmp expected current'
186
187 test_expect_success 'partial commit that involves removal (1)' '
188
189         git rm --cached file &&
190         mv file elif &&
191         git add elif &&
192         git commit -m "Partial: add elif" elif &&
193         git diff-tree --name-status HEAD^ HEAD >current &&
194         echo "A elif" >expected &&
195         test_cmp expected current
196
197 '
198
199 test_expect_success 'partial commit that involves removal (2)' '
200
201         git commit -m "Partial: remove file" file &&
202         git diff-tree --name-status HEAD^ HEAD >current &&
203         echo "D file" >expected &&
204         test_cmp expected current
205
206 '
207
208 test_expect_success 'partial commit that involves removal (3)' '
209
210         git rm --cached elif &&
211         echo elif >elif &&
212         git commit -m "Partial: modify elif" elif &&
213         git diff-tree --name-status HEAD^ HEAD >current &&
214         echo "M elif" >expected &&
215         test_cmp expected current
216
217 '
218
219 author="The Real Author <someguy@his.email.org>"
220 test_expect_success 'amend commit to fix author' '
221
222         oldtick=$GIT_AUTHOR_DATE &&
223         test_tick &&
224         git reset --hard &&
225         git cat-file -p HEAD |
226         sed -e "s/author.*/author $author $oldtick/" \
227                 -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \
228                 expected &&
229         git commit --amend --author="$author" &&
230         git cat-file -p HEAD > current &&
231         test_cmp expected current
232
233 '
234
235 test_expect_success 'amend commit to fix date' '
236
237         test_tick &&
238         newtick=$GIT_AUTHOR_DATE &&
239         git reset --hard &&
240         git cat-file -p HEAD |
241         sed -e "s/author.*/author $author $newtick/" \
242                 -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \
243                 expected &&
244         git commit --amend --date="$newtick" &&
245         git cat-file -p HEAD > current &&
246         test_cmp expected current
247
248 '
249
250 test_expect_success 'commit complains about bogus date' '
251         test_must_fail git commit --amend --date=10.11.2010
252 '
253
254 test_expect_success 'sign off (1)' '
255
256         echo 1 >positive &&
257         git add positive &&
258         git commit -s -m "thank you" &&
259         git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
260         (
261                 echo thank you
262                 echo
263                 git var GIT_COMMITTER_IDENT |
264                 sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
265         ) >expected &&
266         test_cmp expected actual
267
268 '
269
270 test_expect_success 'sign off (2)' '
271
272         echo 2 >positive &&
273         git add positive &&
274         existing="Signed-off-by: Watch This <watchthis@example.com>" &&
275         git commit -s -m "thank you
276
277 $existing" &&
278         git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
279         (
280                 echo thank you
281                 echo
282                 echo $existing
283                 git var GIT_COMMITTER_IDENT |
284                 sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
285         ) >expected &&
286         test_cmp expected actual
287
288 '
289
290 test_expect_success 'signoff gap' '
291
292         echo 3 >positive &&
293         git add positive &&
294         alt="Alt-RFC-822-Header: Value" &&
295         git commit -s -m "welcome
296
297 $alt" &&
298         git cat-file commit HEAD | sed -e "1,/^\$/d" > actual &&
299         (
300                 echo welcome
301                 echo
302                 echo $alt
303                 git var GIT_COMMITTER_IDENT |
304                 sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
305         ) >expected &&
306         test_cmp expected actual
307 '
308
309 test_expect_success 'signoff gap 2' '
310
311         echo 4 >positive &&
312         git add positive &&
313         alt="fixed: 34" &&
314         git commit -s -m "welcome
315
316 We have now
317 $alt" &&
318         git cat-file commit HEAD | sed -e "1,/^\$/d" > actual &&
319         (
320                 echo welcome
321                 echo
322                 echo We have now
323                 echo $alt
324                 echo
325                 git var GIT_COMMITTER_IDENT |
326                 sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
327         ) >expected &&
328         test_cmp expected actual
329 '
330
331 test_expect_success 'multiple -m' '
332
333         >negative &&
334         git add negative &&
335         git commit -m "one" -m "two" -m "three" &&
336         git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
337         (
338                 echo one
339                 echo
340                 echo two
341                 echo
342                 echo three
343         ) >expected &&
344         test_cmp expected actual
345
346 '
347
348 author="The Real Author <someguy@his.email.org>"
349 test_expect_success 'amend commit to fix author' '
350
351         oldtick=$GIT_AUTHOR_DATE &&
352         test_tick &&
353         git reset --hard &&
354         git cat-file -p HEAD |
355         sed -e "s/author.*/author $author $oldtick/" \
356                 -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \
357                 expected &&
358         git commit --amend --author="$author" &&
359         git cat-file -p HEAD > current &&
360         test_cmp expected current
361
362 '
363
364 test_expect_success 'git commit <file> with dirty index' '
365         echo tacocat > elif &&
366         echo tehlulz > chz &&
367         git add chz &&
368         git commit elif -m "tacocat is a palindrome" &&
369         git show --stat | grep elif &&
370         git diff --cached | grep chz
371 '
372
373 test_expect_success 'same tree (single parent)' '
374
375         git reset --hard
376
377         if git commit -m empty
378         then
379                 echo oops -- should have complained
380                 false
381         else
382                 : happy
383         fi
384
385 '
386
387 test_expect_success 'same tree (single parent) --allow-empty' '
388
389         git commit --allow-empty -m "forced empty" &&
390         git cat-file commit HEAD | grep forced
391
392 '
393
394 test_expect_success 'same tree (merge and amend merge)' '
395
396         git checkout -b side HEAD^ &&
397         echo zero >zero &&
398         git add zero &&
399         git commit -m "add zero" &&
400         git checkout master &&
401
402         git merge -s ours side -m "empty ok" &&
403         git diff HEAD^ HEAD >actual &&
404         : >expected &&
405         test_cmp expected actual &&
406
407         git commit --amend -m "empty really ok" &&
408         git diff HEAD^ HEAD >actual &&
409         : >expected &&
410         test_cmp expected actual
411
412 '
413
414 test_expect_success 'amend using the message from another commit' '
415
416         git reset --hard &&
417         test_tick &&
418         git commit --allow-empty -m "old commit" &&
419         old=$(git rev-parse --verify HEAD) &&
420         test_tick &&
421         git commit --allow-empty -m "new commit" &&
422         new=$(git rev-parse --verify HEAD) &&
423         test_tick &&
424         git commit --allow-empty --amend -C "$old" &&
425         git show --pretty="format:%ad %s" "$old" >expected &&
426         git show --pretty="format:%ad %s" HEAD >actual &&
427         test_cmp expected actual
428
429 '
430
431 test_expect_success 'amend using the message from a commit named with tag' '
432
433         git reset --hard &&
434         test_tick &&
435         git commit --allow-empty -m "old commit" &&
436         old=$(git rev-parse --verify HEAD) &&
437         git tag -a -m "tag on old" tagged-old HEAD &&
438         test_tick &&
439         git commit --allow-empty -m "new commit" &&
440         new=$(git rev-parse --verify HEAD) &&
441         test_tick &&
442         git commit --allow-empty --amend -C tagged-old &&
443         git show --pretty="format:%ad %s" "$old" >expected &&
444         git show --pretty="format:%ad %s" HEAD >actual &&
445         test_cmp expected actual
446
447 '
448
449 test_expect_success 'amend can copy notes' '
450
451         git config notes.rewrite.amend true &&
452         git config notes.rewriteRef "refs/notes/*" &&
453         test_commit foo &&
454         git notes add -m"a note" &&
455         test_tick &&
456         git commit --amend -m"new foo" &&
457         test "$(git notes show)" = "a note"
458
459 '
460
461 test_done