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