Merge branch 'bg/xcalloc-nmemb-then-size'
[git] / t / t7102-reset.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Carlos Rica
4 #
5
6 test_description='git reset
7
8 Documented tests for git reset'
9
10 . ./test-lib.sh
11
12 commit_msg () {
13         # String "modify 2nd file (changed)" partly in German
14         # (translated with Google Translate),
15         # encoded in UTF-8, used as a commit log message below.
16         msg="modify 2nd file (ge\303\244ndert)\n"
17         if test -n "$1"
18         then
19                 printf "$msg" | iconv -f utf-8 -t "$1"
20         else
21                 printf "$msg"
22         fi
23 }
24
25 # Tested non-UTF-8 encoding
26 test_encoding="ISO8859-1"
27
28 test_expect_success 'creating initial files and commits' '
29         test_tick &&
30         echo "1st file" >first &&
31         git add first &&
32         git commit -m "create 1st file" &&
33
34         echo "2nd file" >second &&
35         git add second &&
36         git commit -m "create 2nd file" &&
37
38         echo "2nd line 1st file" >>first &&
39         git commit -a -m "modify 1st file" &&
40
41         git rm first &&
42         git mv second secondfile &&
43         git commit -a -m "remove 1st and rename 2nd" &&
44
45         echo "1st line 2nd file" >secondfile &&
46         echo "2nd line 2nd file" >>secondfile &&
47         git -c "i18n.commitEncoding=$test_encoding" commit -a -m "$(commit_msg $test_encoding)" &&
48         head5=$(git rev-parse --verify HEAD)
49 '
50 # git log --pretty=oneline # to see those SHA1 involved
51
52 check_changes () {
53         test "$(git rev-parse HEAD)" = "$1" &&
54         git diff | test_cmp .diff_expect - &&
55         git diff --cached | test_cmp .cached_expect - &&
56         for FILE in *
57         do
58                 echo $FILE':'
59                 cat $FILE || return
60         done | test_cmp .cat_expect -
61 }
62
63 test_expect_success 'reset --hard message' '
64         hex=$(git log -1 --format="%h") &&
65         git reset --hard > .actual &&
66         echo HEAD is now at $hex $(commit_msg) > .expected &&
67         test_cmp .expected .actual
68 '
69
70 test_expect_success 'reset --hard message (ISO8859-1 logoutputencoding)' '
71         hex=$(git log -1 --format="%h") &&
72         git -c "i18n.logOutputEncoding=$test_encoding" reset --hard > .actual &&
73         echo HEAD is now at $hex $(commit_msg $test_encoding) > .expected &&
74         test_cmp .expected .actual
75 '
76
77 >.diff_expect
78 >.cached_expect
79 cat >.cat_expect <<EOF
80 secondfile:
81 1st line 2nd file
82 2nd line 2nd file
83 EOF
84
85 test_expect_success 'giving a non existing revision should fail' '
86         test_must_fail git reset aaaaaa &&
87         test_must_fail git reset --mixed aaaaaa &&
88         test_must_fail git reset --soft aaaaaa &&
89         test_must_fail git reset --hard aaaaaa &&
90         check_changes $head5
91 '
92
93 test_expect_success 'reset --soft with unmerged index should fail' '
94         touch .git/MERGE_HEAD &&
95         echo "100644 44c5b5884550c17758737edcced463447b91d42b 1 un" |
96                 git update-index --index-info &&
97         test_must_fail git reset --soft HEAD &&
98         rm .git/MERGE_HEAD &&
99         git rm --cached -- un
100 '
101
102 test_expect_success \
103         'giving paths with options different than --mixed should fail' '
104         test_must_fail git reset --soft -- first &&
105         test_must_fail git reset --hard -- first &&
106         test_must_fail git reset --soft HEAD^ -- first &&
107         test_must_fail git reset --hard HEAD^ -- first &&
108         check_changes $head5
109 '
110
111 test_expect_success 'giving unrecognized options should fail' '
112         test_must_fail git reset --other &&
113         test_must_fail git reset -o &&
114         test_must_fail git reset --mixed --other &&
115         test_must_fail git reset --mixed -o &&
116         test_must_fail git reset --soft --other &&
117         test_must_fail git reset --soft -o &&
118         test_must_fail git reset --hard --other &&
119         test_must_fail git reset --hard -o &&
120         check_changes $head5
121 '
122
123 test_expect_success \
124         'trying to do reset --soft with pending merge should fail' '
125         git branch branch1 &&
126         git branch branch2 &&
127
128         git checkout branch1 &&
129         echo "3rd line in branch1" >>secondfile &&
130         git commit -a -m "change in branch1" &&
131
132         git checkout branch2 &&
133         echo "3rd line in branch2" >>secondfile &&
134         git commit -a -m "change in branch2" &&
135
136         test_must_fail git merge branch1 &&
137         test_must_fail git reset --soft &&
138
139         printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
140         git commit -a -m "the change in branch2" &&
141
142         git checkout master &&
143         git branch -D branch1 branch2 &&
144         check_changes $head5
145 '
146
147 test_expect_success \
148         'trying to do reset --soft with pending checkout merge should fail' '
149         git branch branch3 &&
150         git branch branch4 &&
151
152         git checkout branch3 &&
153         echo "3rd line in branch3" >>secondfile &&
154         git commit -a -m "line in branch3" &&
155
156         git checkout branch4 &&
157         echo "3rd line in branch4" >>secondfile &&
158
159         git checkout -m branch3 &&
160         test_must_fail git reset --soft &&
161
162         printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
163         git commit -a -m "the line in branch3" &&
164
165         git checkout master &&
166         git branch -D branch3 branch4 &&
167         check_changes $head5
168 '
169
170 test_expect_success \
171         'resetting to HEAD with no changes should succeed and do nothing' '
172         git reset --hard &&
173                 check_changes $head5 &&
174         git reset --hard HEAD &&
175                 check_changes $head5 &&
176         git reset --soft &&
177                 check_changes $head5 &&
178         git reset --soft HEAD &&
179                 check_changes $head5 &&
180         git reset --mixed &&
181                 check_changes $head5 &&
182         git reset --mixed HEAD &&
183                 check_changes $head5 &&
184         git reset &&
185                 check_changes $head5 &&
186         git reset HEAD &&
187                 check_changes $head5
188 '
189
190 >.diff_expect
191 cat >.cached_expect <<EOF
192 diff --git a/secondfile b/secondfile
193 index 1bbba79..44c5b58 100644
194 --- a/secondfile
195 +++ b/secondfile
196 @@ -1 +1,2 @@
197 -2nd file
198 +1st line 2nd file
199 +2nd line 2nd file
200 EOF
201 cat >.cat_expect <<EOF
202 secondfile:
203 1st line 2nd file
204 2nd line 2nd file
205 EOF
206 test_expect_success '--soft reset only should show changes in diff --cached' '
207         git reset --soft HEAD^ &&
208         check_changes d1a4bc3abce4829628ae2dcb0d60ef3d1a78b1c4 &&
209         test "$(git rev-parse ORIG_HEAD)" = \
210                         $head5
211 '
212
213 >.diff_expect
214 >.cached_expect
215 cat >.cat_expect <<EOF
216 secondfile:
217 1st line 2nd file
218 2nd line 2nd file
219 3rd line 2nd file
220 EOF
221 test_expect_success \
222         'changing files and redo the last commit should succeed' '
223         echo "3rd line 2nd file" >>secondfile &&
224         git commit -a -C ORIG_HEAD &&
225         head4=$(git rev-parse --verify HEAD) &&
226         check_changes $head4 &&
227         test "$(git rev-parse ORIG_HEAD)" = \
228                         $head5
229 '
230
231 >.diff_expect
232 >.cached_expect
233 cat >.cat_expect <<EOF
234 first:
235 1st file
236 2nd line 1st file
237 second:
238 2nd file
239 EOF
240 test_expect_success \
241         '--hard reset should change the files and undo commits permanently' '
242         git reset --hard HEAD~2 &&
243         check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
244         test "$(git rev-parse ORIG_HEAD)" = \
245                         $head4
246 '
247
248 >.diff_expect
249 cat >.cached_expect <<EOF
250 diff --git a/first b/first
251 deleted file mode 100644
252 index 8206c22..0000000
253 --- a/first
254 +++ /dev/null
255 @@ -1,2 +0,0 @@
256 -1st file
257 -2nd line 1st file
258 diff --git a/second b/second
259 deleted file mode 100644
260 index 1bbba79..0000000
261 --- a/second
262 +++ /dev/null
263 @@ -1 +0,0 @@
264 -2nd file
265 diff --git a/secondfile b/secondfile
266 new file mode 100644
267 index 0000000..44c5b58
268 --- /dev/null
269 +++ b/secondfile
270 @@ -0,0 +1,2 @@
271 +1st line 2nd file
272 +2nd line 2nd file
273 EOF
274 cat >.cat_expect <<EOF
275 secondfile:
276 1st line 2nd file
277 2nd line 2nd file
278 EOF
279 test_expect_success \
280         'redoing changes adding them without commit them should succeed' '
281         git rm first &&
282         git mv second secondfile &&
283
284         echo "1st line 2nd file" >secondfile &&
285         echo "2nd line 2nd file" >>secondfile &&
286         git add secondfile &&
287         check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e
288 '
289
290 cat >.diff_expect <<EOF
291 diff --git a/first b/first
292 deleted file mode 100644
293 index 8206c22..0000000
294 --- a/first
295 +++ /dev/null
296 @@ -1,2 +0,0 @@
297 -1st file
298 -2nd line 1st file
299 diff --git a/second b/second
300 deleted file mode 100644
301 index 1bbba79..0000000
302 --- a/second
303 +++ /dev/null
304 @@ -1 +0,0 @@
305 -2nd file
306 EOF
307 >.cached_expect
308 cat >.cat_expect <<EOF
309 secondfile:
310 1st line 2nd file
311 2nd line 2nd file
312 EOF
313 test_expect_success '--mixed reset to HEAD should unadd the files' '
314         git reset &&
315         check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
316         test "$(git rev-parse ORIG_HEAD)" = \
317                         ddaefe00f1da16864591c61fdc7adb5d7cd6b74e
318 '
319
320 >.diff_expect
321 >.cached_expect
322 cat >.cat_expect <<EOF
323 secondfile:
324 1st line 2nd file
325 2nd line 2nd file
326 EOF
327 test_expect_success 'redoing the last two commits should succeed' '
328         git add secondfile &&
329         git reset --hard ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
330
331         git rm first &&
332         git mv second secondfile &&
333         git commit -a -m "remove 1st and rename 2nd" &&
334
335         echo "1st line 2nd file" >secondfile &&
336         echo "2nd line 2nd file" >>secondfile &&
337         git -c "i18n.commitEncoding=$test_encoding" commit -a -m "$(commit_msg $test_encoding)" &&
338         check_changes $head5
339 '
340
341 >.diff_expect
342 >.cached_expect
343 cat >.cat_expect <<EOF
344 secondfile:
345 1st line 2nd file
346 2nd line 2nd file
347 3rd line in branch2
348 EOF
349 test_expect_success '--hard reset to HEAD should clear a failed merge' '
350         git branch branch1 &&
351         git branch branch2 &&
352
353         git checkout branch1 &&
354         echo "3rd line in branch1" >>secondfile &&
355         git commit -a -m "change in branch1" &&
356
357         git checkout branch2 &&
358         echo "3rd line in branch2" >>secondfile &&
359         git commit -a -m "change in branch2" &&
360         head3=$(git rev-parse --verify HEAD) &&
361
362         test_must_fail git pull . branch1 &&
363         git reset --hard &&
364         check_changes $head3
365 '
366
367 >.diff_expect
368 >.cached_expect
369 cat >.cat_expect <<EOF
370 secondfile:
371 1st line 2nd file
372 2nd line 2nd file
373 EOF
374 test_expect_success \
375         '--hard reset to ORIG_HEAD should clear a fast-forward merge' '
376         git reset --hard HEAD^ &&
377         check_changes $head5 &&
378
379         git pull . branch1 &&
380         git reset --hard ORIG_HEAD &&
381         check_changes $head5 &&
382
383         git checkout master &&
384         git branch -D branch1 branch2 &&
385         check_changes $head5
386 '
387
388 cat > expect << EOF
389 diff --git a/file1 b/file1
390 index d00491f..7ed6ff8 100644
391 --- a/file1
392 +++ b/file1
393 @@ -1 +1 @@
394 -1
395 +5
396 diff --git a/file2 b/file2
397 deleted file mode 100644
398 index 0cfbf08..0000000
399 --- a/file2
400 +++ /dev/null
401 @@ -1 +0,0 @@
402 -2
403 EOF
404 cat > cached_expect << EOF
405 diff --git a/file4 b/file4
406 new file mode 100644
407 index 0000000..b8626c4
408 --- /dev/null
409 +++ b/file4
410 @@ -0,0 +1 @@
411 +4
412 EOF
413 test_expect_success 'test --mixed <paths>' '
414         echo 1 > file1 &&
415         echo 2 > file2 &&
416         git add file1 file2 &&
417         test_tick &&
418         git commit -m files &&
419         git rm file2 &&
420         echo 3 > file3 &&
421         echo 4 > file4 &&
422         echo 5 > file1 &&
423         git add file1 file3 file4 &&
424         git reset HEAD -- file1 file2 file3 &&
425         test_must_fail git diff --quiet &&
426         git diff > output &&
427         test_cmp output expect &&
428         git diff --cached > output &&
429         test_cmp output cached_expect
430 '
431
432 test_expect_success 'test resetting the index at give paths' '
433
434         mkdir sub &&
435         >sub/file1 &&
436         >sub/file2 &&
437         git update-index --add sub/file1 sub/file2 &&
438         T=$(git write-tree) &&
439         git reset HEAD sub/file2 &&
440         test_must_fail git diff --quiet &&
441         U=$(git write-tree) &&
442         echo "$T" &&
443         echo "$U" &&
444         test_must_fail git diff-index --cached --exit-code "$T" &&
445         test "$T" != "$U"
446
447 '
448
449 test_expect_success 'resetting an unmodified path is a no-op' '
450         git reset --hard &&
451         git reset -- file1 &&
452         git diff-files --exit-code &&
453         git diff-index --cached --exit-code HEAD
454 '
455
456 cat > expect << EOF
457 Unstaged changes after reset:
458 M       file2
459 EOF
460
461 test_expect_success '--mixed refreshes the index' '
462         echo 123 >> file2 &&
463         git reset --mixed HEAD > output &&
464         test_i18ncmp expect output
465 '
466
467 test_expect_success 'resetting specific path that is unmerged' '
468         git rm --cached file2 &&
469         F1=$(git rev-parse HEAD:file1) &&
470         F2=$(git rev-parse HEAD:file2) &&
471         F3=$(git rev-parse HEAD:secondfile) &&
472         {
473                 echo "100644 $F1 1      file2" &&
474                 echo "100644 $F2 2      file2" &&
475                 echo "100644 $F3 3      file2"
476         } | git update-index --index-info &&
477         git ls-files -u &&
478         git reset HEAD file2 &&
479         test_must_fail git diff --quiet &&
480         git diff-index --exit-code --cached HEAD
481 '
482
483 test_expect_success 'disambiguation (1)' '
484
485         git reset --hard &&
486         >secondfile &&
487         git add secondfile &&
488         git reset secondfile &&
489         test_must_fail git diff --quiet -- secondfile &&
490         test -z "$(git diff --cached --name-only)" &&
491         test -f secondfile &&
492         test_must_be_empty secondfile
493
494 '
495
496 test_expect_success 'disambiguation (2)' '
497
498         git reset --hard &&
499         >secondfile &&
500         git add secondfile &&
501         rm -f secondfile &&
502         test_must_fail git reset secondfile &&
503         test -n "$(git diff --cached --name-only -- secondfile)" &&
504         test ! -f secondfile
505
506 '
507
508 test_expect_success 'disambiguation (3)' '
509
510         git reset --hard &&
511         >secondfile &&
512         git add secondfile &&
513         rm -f secondfile &&
514         git reset HEAD secondfile &&
515         test_must_fail git diff --quiet &&
516         test -z "$(git diff --cached --name-only)" &&
517         test ! -f secondfile
518
519 '
520
521 test_expect_success 'disambiguation (4)' '
522
523         git reset --hard &&
524         >secondfile &&
525         git add secondfile &&
526         rm -f secondfile &&
527         git reset -- secondfile &&
528         test_must_fail git diff --quiet &&
529         test -z "$(git diff --cached --name-only)" &&
530         test ! -f secondfile
531 '
532
533 test_expect_success 'reset with paths accepts tree' '
534         # for simpler tests, drop last commit containing added files
535         git reset --hard HEAD^ &&
536         git reset HEAD^^{tree} -- . &&
537         git diff --cached HEAD^ --exit-code &&
538         git diff HEAD --exit-code
539 '
540
541 test_expect_success 'reset -N keeps removed files as intent-to-add' '
542         echo new-file >new-file &&
543         git add new-file &&
544         git reset -N HEAD &&
545
546         tree=$(git write-tree) &&
547         git ls-tree $tree new-file >actual &&
548         >expect &&
549         test_cmp expect actual &&
550
551         git diff --name-only >actual &&
552         echo new-file >expect &&
553         test_cmp expect actual
554 '
555
556 test_expect_success 'reset --mixed sets up work tree' '
557         git init mixed_worktree &&
558         (
559                 cd mixed_worktree &&
560                 test_commit dummy
561         ) &&
562         : >expect &&
563         git --git-dir=mixed_worktree/.git --work-tree=mixed_worktree reset >actual &&
564         test_cmp expect actual
565 '
566
567 test_done