Merge branch 'ye/doc-http-proto' into maint
[git] / t / t3903-stash.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Johannes E Schindelin
4 #
5
6 test_description='Test git stash'
7
8 . ./test-lib.sh
9
10 test_expect_success 'stash some dirty working directory' '
11         echo 1 > file &&
12         git add file &&
13         test_tick &&
14         git commit -m initial &&
15         echo 2 > file &&
16         git add file &&
17         echo 3 > file &&
18         test_tick &&
19         git stash &&
20         git diff-files --quiet &&
21         git diff-index --cached --quiet HEAD
22 '
23
24 cat > expect << EOF
25 diff --git a/file b/file
26 index 0cfbf08..00750ed 100644
27 --- a/file
28 +++ b/file
29 @@ -1 +1 @@
30 -2
31 +3
32 EOF
33
34 test_expect_success 'parents of stash' '
35         test $(git rev-parse stash^) = $(git rev-parse HEAD) &&
36         git diff stash^2..stash > output &&
37         test_cmp output expect
38 '
39
40 test_expect_success 'applying bogus stash does nothing' '
41         test_must_fail git stash apply stash@{1} &&
42         echo 1 >expect &&
43         test_cmp expect file
44 '
45
46 test_expect_success 'apply does not need clean working directory' '
47         echo 4 >other-file &&
48         git add other-file &&
49         echo 5 >other-file &&
50         git stash apply &&
51         echo 3 >expect &&
52         test_cmp expect file
53 '
54
55 test_expect_success 'apply does not clobber working directory changes' '
56         git reset --hard &&
57         echo 4 >file &&
58         test_must_fail git stash apply &&
59         echo 4 >expect &&
60         test_cmp expect file
61 '
62
63 test_expect_success 'apply stashed changes' '
64         git reset --hard &&
65         echo 5 >other-file &&
66         git add other-file &&
67         test_tick &&
68         git commit -m other-file &&
69         git stash apply &&
70         test 3 = $(cat file) &&
71         test 1 = $(git show :file) &&
72         test 1 = $(git show HEAD:file)
73 '
74
75 test_expect_success 'apply stashed changes (including index)' '
76         git reset --hard HEAD^ &&
77         echo 6 > other-file &&
78         git add other-file &&
79         test_tick &&
80         git commit -m other-file &&
81         git stash apply --index &&
82         test 3 = $(cat file) &&
83         test 2 = $(git show :file) &&
84         test 1 = $(git show HEAD:file)
85 '
86
87 test_expect_success 'unstashing in a subdirectory' '
88         git reset --hard HEAD &&
89         mkdir subdir &&
90         (
91                 cd subdir &&
92                 git stash apply
93         )
94 '
95
96 test_expect_success 'drop top stash' '
97         git reset --hard &&
98         git stash list > stashlist1 &&
99         echo 7 > file &&
100         git stash &&
101         git stash drop &&
102         git stash list > stashlist2 &&
103         test_cmp stashlist1 stashlist2 &&
104         git stash apply &&
105         test 3 = $(cat file) &&
106         test 1 = $(git show :file) &&
107         test 1 = $(git show HEAD:file)
108 '
109
110 test_expect_success 'drop middle stash' '
111         git reset --hard &&
112         echo 8 > file &&
113         git stash &&
114         echo 9 > file &&
115         git stash &&
116         git stash drop stash@{1} &&
117         test 2 = $(git stash list | wc -l) &&
118         git stash apply &&
119         test 9 = $(cat file) &&
120         test 1 = $(git show :file) &&
121         test 1 = $(git show HEAD:file) &&
122         git reset --hard &&
123         git stash drop &&
124         git stash apply &&
125         test 3 = $(cat file) &&
126         test 1 = $(git show :file) &&
127         test 1 = $(git show HEAD:file)
128 '
129
130 test_expect_success 'stash pop' '
131         git reset --hard &&
132         git stash pop &&
133         test 3 = $(cat file) &&
134         test 1 = $(git show :file) &&
135         test 1 = $(git show HEAD:file) &&
136         test 0 = $(git stash list | wc -l)
137 '
138
139 cat > expect << EOF
140 diff --git a/file2 b/file2
141 new file mode 100644
142 index 0000000..1fe912c
143 --- /dev/null
144 +++ b/file2
145 @@ -0,0 +1 @@
146 +bar2
147 EOF
148
149 cat > expect1 << EOF
150 diff --git a/file b/file
151 index 257cc56..5716ca5 100644
152 --- a/file
153 +++ b/file
154 @@ -1 +1 @@
155 -foo
156 +bar
157 EOF
158
159 cat > expect2 << EOF
160 diff --git a/file b/file
161 index 7601807..5716ca5 100644
162 --- a/file
163 +++ b/file
164 @@ -1 +1 @@
165 -baz
166 +bar
167 diff --git a/file2 b/file2
168 new file mode 100644
169 index 0000000..1fe912c
170 --- /dev/null
171 +++ b/file2
172 @@ -0,0 +1 @@
173 +bar2
174 EOF
175
176 test_expect_success 'stash branch' '
177         echo foo > file &&
178         git commit file -m first &&
179         echo bar > file &&
180         echo bar2 > file2 &&
181         git add file2 &&
182         git stash &&
183         echo baz > file &&
184         git commit file -m second &&
185         git stash branch stashbranch &&
186         test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
187         test $(git rev-parse HEAD) = $(git rev-parse master^) &&
188         git diff --cached > output &&
189         test_cmp output expect &&
190         git diff > output &&
191         test_cmp output expect1 &&
192         git add file &&
193         git commit -m alternate\ second &&
194         git diff master..stashbranch > output &&
195         test_cmp output expect2 &&
196         test 0 = $(git stash list | wc -l)
197 '
198
199 test_expect_success 'apply -q is quiet' '
200         echo foo > file &&
201         git stash &&
202         git stash apply -q > output.out 2>&1 &&
203         test_must_be_empty output.out
204 '
205
206 test_expect_success 'save -q is quiet' '
207         git stash save --quiet > output.out 2>&1 &&
208         test_must_be_empty output.out
209 '
210
211 test_expect_success 'pop -q is quiet' '
212         git stash pop -q > output.out 2>&1 &&
213         test_must_be_empty output.out
214 '
215
216 test_expect_success 'pop -q --index works and is quiet' '
217         echo foo > file &&
218         git add file &&
219         git stash save --quiet &&
220         git stash pop -q --index > output.out 2>&1 &&
221         test foo = "$(git show :file)" &&
222         test_must_be_empty output.out
223 '
224
225 test_expect_success 'drop -q is quiet' '
226         git stash &&
227         git stash drop -q > output.out 2>&1 &&
228         test_must_be_empty output.out
229 '
230
231 test_expect_success 'stash -k' '
232         echo bar3 > file &&
233         echo bar4 > file2 &&
234         git add file2 &&
235         git stash -k &&
236         test bar,bar4 = $(cat file),$(cat file2)
237 '
238
239 test_expect_success 'stash --no-keep-index' '
240         echo bar33 > file &&
241         echo bar44 > file2 &&
242         git add file2 &&
243         git stash --no-keep-index &&
244         test bar,bar2 = $(cat file),$(cat file2)
245 '
246
247 test_expect_success 'stash --invalid-option' '
248         echo bar5 > file &&
249         echo bar6 > file2 &&
250         git add file2 &&
251         test_must_fail git stash --invalid-option &&
252         test_must_fail git stash save --invalid-option &&
253         test bar5,bar6 = $(cat file),$(cat file2) &&
254         git stash -- -message-starting-with-dash &&
255         test bar,bar2 = $(cat file),$(cat file2)
256 '
257
258 test_expect_success 'stash an added file' '
259         git reset --hard &&
260         echo new >file3 &&
261         git add file3 &&
262         git stash save "added file" &&
263         ! test -r file3 &&
264         git stash apply &&
265         test new = "$(cat file3)"
266 '
267
268 test_expect_success 'stash rm then recreate' '
269         git reset --hard &&
270         git rm file &&
271         echo bar7 >file &&
272         git stash save "rm then recreate" &&
273         test bar = "$(cat file)" &&
274         git stash apply &&
275         test bar7 = "$(cat file)"
276 '
277
278 test_expect_success 'stash rm and ignore' '
279         git reset --hard &&
280         git rm file &&
281         echo file >.gitignore &&
282         git stash save "rm and ignore" &&
283         test bar = "$(cat file)" &&
284         test file = "$(cat .gitignore)" &&
285         git stash apply &&
286         ! test -r file &&
287         test file = "$(cat .gitignore)"
288 '
289
290 test_expect_success 'stash rm and ignore (stage .gitignore)' '
291         git reset --hard &&
292         git rm file &&
293         echo file >.gitignore &&
294         git add .gitignore &&
295         git stash save "rm and ignore (stage .gitignore)" &&
296         test bar = "$(cat file)" &&
297         ! test -r .gitignore &&
298         git stash apply &&
299         ! test -r file &&
300         test file = "$(cat .gitignore)"
301 '
302
303 test_expect_success SYMLINKS 'stash file to symlink' '
304         git reset --hard &&
305         rm file &&
306         ln -s file2 file &&
307         git stash save "file to symlink" &&
308         test -f file &&
309         test bar = "$(cat file)" &&
310         git stash apply &&
311         case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
312 '
313
314 test_expect_success SYMLINKS 'stash file to symlink (stage rm)' '
315         git reset --hard &&
316         git rm file &&
317         ln -s file2 file &&
318         git stash save "file to symlink (stage rm)" &&
319         test -f file &&
320         test bar = "$(cat file)" &&
321         git stash apply &&
322         case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
323 '
324
325 test_expect_success SYMLINKS 'stash file to symlink (full stage)' '
326         git reset --hard &&
327         rm file &&
328         ln -s file2 file &&
329         git add file &&
330         git stash save "file to symlink (full stage)" &&
331         test -f file &&
332         test bar = "$(cat file)" &&
333         git stash apply &&
334         case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
335 '
336
337 # This test creates a commit with a symlink used for the following tests
338
339 test_expect_success 'stash symlink to file' '
340         git reset --hard &&
341         test_ln_s_add file filelink &&
342         git commit -m "Add symlink" &&
343         rm filelink &&
344         cp file filelink &&
345         git stash save "symlink to file"
346 '
347
348 test_expect_success SYMLINKS 'this must have re-created the symlink' '
349         test -h filelink &&
350         case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
351 '
352
353 test_expect_success 'unstash must re-create the file' '
354         git stash apply &&
355         ! test -h filelink &&
356         test bar = "$(cat file)"
357 '
358
359 test_expect_success 'stash symlink to file (stage rm)' '
360         git reset --hard &&
361         git rm filelink &&
362         cp file filelink &&
363         git stash save "symlink to file (stage rm)"
364 '
365
366 test_expect_success SYMLINKS 'this must have re-created the symlink' '
367         test -h filelink &&
368         case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
369 '
370
371 test_expect_success 'unstash must re-create the file' '
372         git stash apply &&
373         ! test -h filelink &&
374         test bar = "$(cat file)"
375 '
376
377 test_expect_success 'stash symlink to file (full stage)' '
378         git reset --hard &&
379         rm filelink &&
380         cp file filelink &&
381         git add filelink &&
382         git stash save "symlink to file (full stage)"
383 '
384
385 test_expect_success SYMLINKS 'this must have re-created the symlink' '
386         test -h filelink &&
387         case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
388 '
389
390 test_expect_success 'unstash must re-create the file' '
391         git stash apply &&
392         ! test -h filelink &&
393         test bar = "$(cat file)"
394 '
395
396 test_expect_failure 'stash directory to file' '
397         git reset --hard &&
398         mkdir dir &&
399         echo foo >dir/file &&
400         git add dir/file &&
401         git commit -m "Add file in dir" &&
402         rm -fr dir &&
403         echo bar >dir &&
404         git stash save "directory to file" &&
405         test -d dir &&
406         test foo = "$(cat dir/file)" &&
407         test_must_fail git stash apply &&
408         test bar = "$(cat dir)" &&
409         git reset --soft HEAD^
410 '
411
412 test_expect_failure 'stash file to directory' '
413         git reset --hard &&
414         rm file &&
415         mkdir file &&
416         echo foo >file/file &&
417         git stash save "file to directory" &&
418         test -f file &&
419         test bar = "$(cat file)" &&
420         git stash apply &&
421         test -f file/file &&
422         test foo = "$(cat file/file)"
423 '
424
425 test_expect_success 'stash branch - no stashes on stack, stash-like argument' '
426         git stash clear &&
427         test_when_finished "git reset --hard HEAD" &&
428         git reset --hard &&
429         echo foo >> file &&
430         STASH_ID=$(git stash create) &&
431         git reset --hard &&
432         git stash branch stash-branch ${STASH_ID} &&
433         test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" &&
434         test $(git ls-files --modified | wc -l) -eq 1
435 '
436
437 test_expect_success 'stash branch - stashes on stack, stash-like argument' '
438         git stash clear &&
439         test_when_finished "git reset --hard HEAD" &&
440         git reset --hard &&
441         echo foo >> file &&
442         git stash &&
443         test_when_finished "git stash drop" &&
444         echo bar >> file &&
445         STASH_ID=$(git stash create) &&
446         git reset --hard &&
447         git stash branch stash-branch ${STASH_ID} &&
448         test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" &&
449         test $(git ls-files --modified | wc -l) -eq 1
450 '
451
452 test_expect_success 'stash show format defaults to --stat' '
453         git stash clear &&
454         test_when_finished "git reset --hard HEAD" &&
455         git reset --hard &&
456         echo foo >> file &&
457         git stash &&
458         test_when_finished "git stash drop" &&
459         echo bar >> file &&
460         STASH_ID=$(git stash create) &&
461         git reset --hard &&
462         cat >expected <<-EOF &&
463          file | 1 +
464          1 file changed, 1 insertion(+)
465         EOF
466         git stash show ${STASH_ID} >actual &&
467         test_i18ncmp expected actual
468 '
469
470 test_expect_success 'stash show - stashes on stack, stash-like argument' '
471         git stash clear &&
472         test_when_finished "git reset --hard HEAD" &&
473         git reset --hard &&
474         echo foo >> file &&
475         git stash &&
476         test_when_finished "git stash drop" &&
477         echo bar >> file &&
478         STASH_ID=$(git stash create) &&
479         git reset --hard &&
480         echo "1 0       file" >expected &&
481         git stash show --numstat ${STASH_ID} >actual &&
482         test_cmp expected actual
483 '
484
485 test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
486         git stash clear &&
487         test_when_finished "git reset --hard HEAD" &&
488         git reset --hard &&
489         echo foo >> file &&
490         git stash &&
491         test_when_finished "git stash drop" &&
492         echo bar >> file &&
493         STASH_ID=$(git stash create) &&
494         git reset --hard &&
495         cat >expected <<-EOF &&
496         diff --git a/file b/file
497         index 7601807..935fbd3 100644
498         --- a/file
499         +++ b/file
500         @@ -1 +1,2 @@
501          baz
502         +bar
503         EOF
504         git stash show -p ${STASH_ID} >actual &&
505         test_cmp expected actual
506 '
507
508 test_expect_success 'stash show - no stashes on stack, stash-like argument' '
509         git stash clear &&
510         test_when_finished "git reset --hard HEAD" &&
511         git reset --hard &&
512         echo foo >> file &&
513         STASH_ID=$(git stash create) &&
514         git reset --hard &&
515         echo "1 0       file" >expected &&
516         git stash show --numstat ${STASH_ID} >actual &&
517         test_cmp expected actual
518 '
519
520 test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
521         git stash clear &&
522         test_when_finished "git reset --hard HEAD" &&
523         git reset --hard &&
524         echo foo >> file &&
525         STASH_ID=$(git stash create) &&
526         git reset --hard &&
527         cat >expected <<-EOF &&
528         diff --git a/file b/file
529         index 7601807..71b52c4 100644
530         --- a/file
531         +++ b/file
532         @@ -1 +1,2 @@
533          baz
534         +foo
535         EOF
536         git stash show -p ${STASH_ID} >actual &&
537         test_cmp expected actual
538 '
539
540 test_expect_success 'stash drop - fail early if specified stash is not a stash reference' '
541         git stash clear &&
542         test_when_finished "git reset --hard HEAD && git stash clear" &&
543         git reset --hard &&
544         echo foo > file &&
545         git stash &&
546         echo bar > file &&
547         git stash &&
548         test_must_fail git stash drop $(git rev-parse stash@{0}) &&
549         git stash pop &&
550         test bar = "$(cat file)" &&
551         git reset --hard HEAD
552 '
553
554 test_expect_success 'stash pop - fail early if specified stash is not a stash reference' '
555         git stash clear &&
556         test_when_finished "git reset --hard HEAD && git stash clear" &&
557         git reset --hard &&
558         echo foo > file &&
559         git stash &&
560         echo bar > file &&
561         git stash &&
562         test_must_fail git stash pop $(git rev-parse stash@{0}) &&
563         git stash pop &&
564         test bar = "$(cat file)" &&
565         git reset --hard HEAD
566 '
567
568 test_expect_success 'ref with non-existent reflog' '
569         git stash clear &&
570         echo bar5 > file &&
571         echo bar6 > file2 &&
572         git add file2 &&
573         git stash &&
574         test_must_fail git rev-parse --quiet --verify does-not-exist &&
575         test_must_fail git stash drop does-not-exist &&
576         test_must_fail git stash drop does-not-exist@{0} &&
577         test_must_fail git stash pop does-not-exist &&
578         test_must_fail git stash pop does-not-exist@{0} &&
579         test_must_fail git stash apply does-not-exist &&
580         test_must_fail git stash apply does-not-exist@{0} &&
581         test_must_fail git stash show does-not-exist &&
582         test_must_fail git stash show does-not-exist@{0} &&
583         test_must_fail git stash branch tmp does-not-exist &&
584         test_must_fail git stash branch tmp does-not-exist@{0} &&
585         git stash drop
586 '
587
588 test_expect_success 'invalid ref of the form stash@{n}, n >= N' '
589         git stash clear &&
590         test_must_fail git stash drop stash@{0} &&
591         echo bar5 > file &&
592         echo bar6 > file2 &&
593         git add file2 &&
594         git stash &&
595         test_must_fail git stash drop stash@{1} &&
596         test_must_fail git stash pop stash@{1} &&
597         test_must_fail git stash apply stash@{1} &&
598         test_must_fail git stash show stash@{1} &&
599         test_must_fail git stash branch tmp stash@{1} &&
600         git stash drop
601 '
602
603 test_expect_success 'stash branch should not drop the stash if the branch exists' '
604         git stash clear &&
605         echo foo >file &&
606         git add file &&
607         git commit -m initial &&
608         echo bar >file &&
609         git stash &&
610         test_must_fail git stash branch master stash@{0} &&
611         git rev-parse stash@{0} --
612 '
613
614 test_expect_success 'stash apply shows status same as git status (relative to current directory)' '
615         git stash clear &&
616         echo 1 >subdir/subfile1 &&
617         echo 2 >subdir/subfile2 &&
618         git add subdir/subfile1 &&
619         git commit -m subdir &&
620         (
621                 cd subdir &&
622                 echo x >subfile1 &&
623                 echo x >../file &&
624                 git status >../expect &&
625                 git stash &&
626                 sane_unset GIT_MERGE_VERBOSITY &&
627                 git stash apply
628         ) |
629         sed -e 1,2d >actual && # drop "Saved..." and "HEAD is now..."
630         test_i18ncmp expect actual
631 '
632
633 cat > expect << EOF
634 diff --git a/HEAD b/HEAD
635 new file mode 100644
636 index 0000000..fe0cbee
637 --- /dev/null
638 +++ b/HEAD
639 @@ -0,0 +1 @@
640 +file-not-a-ref
641 EOF
642
643 test_expect_success 'stash where working directory contains "HEAD" file' '
644         git stash clear &&
645         git reset --hard &&
646         echo file-not-a-ref > HEAD &&
647         git add HEAD &&
648         test_tick &&
649         git stash &&
650         git diff-files --quiet &&
651         git diff-index --cached --quiet HEAD &&
652         test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" &&
653         git diff stash^..stash > output &&
654         test_cmp output expect
655 '
656
657 test_expect_success 'store called with invalid commit' '
658         test_must_fail git stash store foo
659 '
660
661 test_expect_success 'store updates stash ref and reflog' '
662         git stash clear &&
663         git reset --hard &&
664         echo quux >bazzy &&
665         git add bazzy &&
666         STASH_ID=$(git stash create) &&
667         git reset --hard &&
668         ! grep quux bazzy &&
669         git stash store -m quuxery $STASH_ID &&
670         test $(cat .git/refs/stash) = $STASH_ID &&
671         grep $STASH_ID .git/logs/refs/stash &&
672         git stash pop &&
673         grep quux bazzy
674 '
675
676 test_expect_success 'handle stash specification with spaces' '
677         git stash clear &&
678         echo pig >file &&
679         git stash &&
680         stamp=$(git log -g --format="%cd" -1 refs/stash) &&
681         test_tick &&
682         echo cow >file &&
683         git stash &&
684         git stash apply "stash@{$stamp}" &&
685         grep pig file
686 '
687
688 test_done