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