stash: handle staged changes in skip-worktree files correctly
[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 expect output
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 >expected &&
103         echo 7 >file &&
104         git stash &&
105         git stash drop &&
106         git stash list >actual &&
107         test_cmp expected actual &&
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 'drop middle stash by index' '
135         git reset --hard &&
136         echo 8 >file &&
137         git stash &&
138         echo 9 >file &&
139         git stash &&
140         git stash drop 1 &&
141         test 2 = $(git stash list | wc -l) &&
142         git stash apply &&
143         test 9 = $(cat file) &&
144         test 1 = $(git show :file) &&
145         test 1 = $(git show HEAD:file) &&
146         git reset --hard &&
147         git stash drop &&
148         git stash apply &&
149         test 3 = $(cat file) &&
150         test 1 = $(git show :file) &&
151         test 1 = $(git show HEAD:file)
152 '
153
154 test_expect_success 'stash pop' '
155         git reset --hard &&
156         git stash pop &&
157         test 3 = $(cat file) &&
158         test 1 = $(git show :file) &&
159         test 1 = $(git show HEAD:file) &&
160         test 0 = $(git stash list | wc -l)
161 '
162
163 cat >expect <<EOF
164 diff --git a/file2 b/file2
165 new file mode 100644
166 index 0000000..1fe912c
167 --- /dev/null
168 +++ b/file2
169 @@ -0,0 +1 @@
170 +bar2
171 EOF
172
173 cat >expect1 <<EOF
174 diff --git a/file b/file
175 index 257cc56..5716ca5 100644
176 --- a/file
177 +++ b/file
178 @@ -1 +1 @@
179 -foo
180 +bar
181 EOF
182
183 cat >expect2 <<EOF
184 diff --git a/file b/file
185 index 7601807..5716ca5 100644
186 --- a/file
187 +++ b/file
188 @@ -1 +1 @@
189 -baz
190 +bar
191 diff --git a/file2 b/file2
192 new file mode 100644
193 index 0000000..1fe912c
194 --- /dev/null
195 +++ b/file2
196 @@ -0,0 +1 @@
197 +bar2
198 EOF
199
200 test_expect_success 'stash branch' '
201         echo foo >file &&
202         git commit file -m first &&
203         echo bar >file &&
204         echo bar2 >file2 &&
205         git add file2 &&
206         git stash &&
207         echo baz >file &&
208         git commit file -m second &&
209         git stash branch stashbranch &&
210         test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
211         test $(git rev-parse HEAD) = $(git rev-parse master^) &&
212         git diff --cached >output &&
213         test_cmp expect output &&
214         git diff >output &&
215         test_cmp expect1 output &&
216         git add file &&
217         git commit -m alternate\ second &&
218         git diff master..stashbranch >output &&
219         test_cmp output expect2 &&
220         test 0 = $(git stash list | wc -l)
221 '
222
223 test_expect_success 'apply -q is quiet' '
224         echo foo >file &&
225         git stash &&
226         git stash apply -q >output.out 2>&1 &&
227         test_must_be_empty output.out
228 '
229
230 test_expect_success 'save -q is quiet' '
231         git stash save --quiet >output.out 2>&1 &&
232         test_must_be_empty output.out
233 '
234
235 test_expect_success 'pop -q is quiet' '
236         git stash pop -q >output.out 2>&1 &&
237         test_must_be_empty output.out
238 '
239
240 test_expect_success 'pop -q --index works and is quiet' '
241         echo foo >file &&
242         git add file &&
243         git stash save --quiet &&
244         git stash pop -q --index >output.out 2>&1 &&
245         test foo = "$(git show :file)" &&
246         test_must_be_empty output.out
247 '
248
249 test_expect_success 'drop -q is quiet' '
250         git stash &&
251         git stash drop -q >output.out 2>&1 &&
252         test_must_be_empty output.out
253 '
254
255 test_expect_success 'stash -k' '
256         echo bar3 >file &&
257         echo bar4 >file2 &&
258         git add file2 &&
259         git stash -k &&
260         test bar,bar4 = $(cat file),$(cat file2)
261 '
262
263 test_expect_success 'stash --no-keep-index' '
264         echo bar33 >file &&
265         echo bar44 >file2 &&
266         git add file2 &&
267         git stash --no-keep-index &&
268         test bar,bar2 = $(cat file),$(cat file2)
269 '
270
271 test_expect_success 'stash --invalid-option' '
272         echo bar5 >file &&
273         echo bar6 >file2 &&
274         git add file2 &&
275         test_must_fail git stash --invalid-option &&
276         test_must_fail git stash save --invalid-option &&
277         test bar5,bar6 = $(cat file),$(cat file2)
278 '
279
280 test_expect_success 'stash an added file' '
281         git reset --hard &&
282         echo new >file3 &&
283         git add file3 &&
284         git stash save "added file" &&
285         ! test -r file3 &&
286         git stash apply &&
287         test new = "$(cat file3)"
288 '
289
290 test_expect_success 'stash --intent-to-add file' '
291         git reset --hard &&
292         echo new >file4 &&
293         git add --intent-to-add file4 &&
294         test_when_finished "git rm -f file4" &&
295         test_must_fail git stash
296 '
297
298 test_expect_success 'stash rm then recreate' '
299         git reset --hard &&
300         git rm file &&
301         echo bar7 >file &&
302         git stash save "rm then recreate" &&
303         test bar = "$(cat file)" &&
304         git stash apply &&
305         test bar7 = "$(cat file)"
306 '
307
308 test_expect_success 'stash rm and ignore' '
309         git reset --hard &&
310         git rm file &&
311         echo file >.gitignore &&
312         git stash save "rm and ignore" &&
313         test bar = "$(cat file)" &&
314         test file = "$(cat .gitignore)" &&
315         git stash apply &&
316         ! test -r file &&
317         test file = "$(cat .gitignore)"
318 '
319
320 test_expect_success 'stash rm and ignore (stage .gitignore)' '
321         git reset --hard &&
322         git rm file &&
323         echo file >.gitignore &&
324         git add .gitignore &&
325         git stash save "rm and ignore (stage .gitignore)" &&
326         test bar = "$(cat file)" &&
327         ! test -r .gitignore &&
328         git stash apply &&
329         ! test -r file &&
330         test file = "$(cat .gitignore)"
331 '
332
333 test_expect_success SYMLINKS 'stash file to symlink' '
334         git reset --hard &&
335         rm file &&
336         ln -s file2 file &&
337         git stash save "file to symlink" &&
338         test -f file &&
339         test bar = "$(cat file)" &&
340         git stash apply &&
341         case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
342 '
343
344 test_expect_success SYMLINKS 'stash file to symlink (stage rm)' '
345         git reset --hard &&
346         git rm file &&
347         ln -s file2 file &&
348         git stash save "file to symlink (stage rm)" &&
349         test -f file &&
350         test bar = "$(cat file)" &&
351         git stash apply &&
352         case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
353 '
354
355 test_expect_success SYMLINKS 'stash file to symlink (full stage)' '
356         git reset --hard &&
357         rm file &&
358         ln -s file2 file &&
359         git add file &&
360         git stash save "file to symlink (full stage)" &&
361         test -f file &&
362         test bar = "$(cat file)" &&
363         git stash apply &&
364         case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
365 '
366
367 # This test creates a commit with a symlink used for the following tests
368
369 test_expect_success 'stash symlink to file' '
370         git reset --hard &&
371         test_ln_s_add file filelink &&
372         git commit -m "Add symlink" &&
373         rm filelink &&
374         cp file filelink &&
375         git stash save "symlink to file"
376 '
377
378 test_expect_success SYMLINKS 'this must have re-created the symlink' '
379         test -h filelink &&
380         case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
381 '
382
383 test_expect_success 'unstash must re-create the file' '
384         git stash apply &&
385         ! test -h filelink &&
386         test bar = "$(cat file)"
387 '
388
389 test_expect_success 'stash symlink to file (stage rm)' '
390         git reset --hard &&
391         git rm filelink &&
392         cp file filelink &&
393         git stash save "symlink to file (stage rm)"
394 '
395
396 test_expect_success SYMLINKS 'this must have re-created the symlink' '
397         test -h filelink &&
398         case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
399 '
400
401 test_expect_success 'unstash must re-create the file' '
402         git stash apply &&
403         ! test -h filelink &&
404         test bar = "$(cat file)"
405 '
406
407 test_expect_success 'stash symlink to file (full stage)' '
408         git reset --hard &&
409         rm filelink &&
410         cp file filelink &&
411         git add filelink &&
412         git stash save "symlink to file (full stage)"
413 '
414
415 test_expect_success SYMLINKS 'this must have re-created the symlink' '
416         test -h filelink &&
417         case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
418 '
419
420 test_expect_success 'unstash must re-create the file' '
421         git stash apply &&
422         ! test -h filelink &&
423         test bar = "$(cat file)"
424 '
425
426 test_expect_failure 'stash directory to file' '
427         git reset --hard &&
428         mkdir dir &&
429         echo foo >dir/file &&
430         git add dir/file &&
431         git commit -m "Add file in dir" &&
432         rm -fr dir &&
433         echo bar >dir &&
434         git stash save "directory to file" &&
435         test -d dir &&
436         test foo = "$(cat dir/file)" &&
437         test_must_fail git stash apply &&
438         test bar = "$(cat dir)" &&
439         git reset --soft HEAD^
440 '
441
442 test_expect_failure 'stash file to directory' '
443         git reset --hard &&
444         rm file &&
445         mkdir file &&
446         echo foo >file/file &&
447         git stash save "file to directory" &&
448         test -f file &&
449         test bar = "$(cat file)" &&
450         git stash apply &&
451         test -f file/file &&
452         test foo = "$(cat file/file)"
453 '
454
455 test_expect_success 'giving too many ref arguments does not modify files' '
456         git stash clear &&
457         test_when_finished "git reset --hard HEAD" &&
458         echo foo >file2 &&
459         git stash &&
460         echo bar >file2 &&
461         git stash &&
462         test-tool chmtime =123456789 file2 &&
463         for type in apply pop "branch stash-branch"
464         do
465                 test_must_fail git stash $type stash@{0} stash@{1} 2>err &&
466                 test_i18ngrep "Too many revisions" err &&
467                 test 123456789 = $(test-tool chmtime -g file2) || return 1
468         done
469 '
470
471 test_expect_success 'drop: too many arguments errors out (does nothing)' '
472         git stash list >expect &&
473         test_must_fail git stash drop stash@{0} stash@{1} 2>err &&
474         test_i18ngrep "Too many revisions" err &&
475         git stash list >actual &&
476         test_cmp expect actual
477 '
478
479 test_expect_success 'show: too many arguments errors out (does nothing)' '
480         test_must_fail git stash show stash@{0} stash@{1} 2>err 1>out &&
481         test_i18ngrep "Too many revisions" err &&
482         test_must_be_empty out
483 '
484
485 test_expect_success 'stash create - no changes' '
486         git stash clear &&
487         test_when_finished "git reset --hard HEAD" &&
488         git reset --hard &&
489         git stash create >actual &&
490         test_must_be_empty actual
491 '
492
493 test_expect_success 'stash branch - no stashes on stack, stash-like argument' '
494         git stash clear &&
495         test_when_finished "git reset --hard HEAD" &&
496         git reset --hard &&
497         echo foo >>file &&
498         STASH_ID=$(git stash create) &&
499         git reset --hard &&
500         git stash branch stash-branch ${STASH_ID} &&
501         test_when_finished "git reset --hard HEAD && git checkout master &&
502         git branch -D stash-branch" &&
503         test $(git ls-files --modified | wc -l) -eq 1
504 '
505
506 test_expect_success 'stash branch - stashes on stack, stash-like argument' '
507         git stash clear &&
508         test_when_finished "git reset --hard HEAD" &&
509         git reset --hard &&
510         echo foo >>file &&
511         git stash &&
512         test_when_finished "git stash drop" &&
513         echo bar >>file &&
514         STASH_ID=$(git stash create) &&
515         git reset --hard &&
516         git stash branch stash-branch ${STASH_ID} &&
517         test_when_finished "git reset --hard HEAD && git checkout master &&
518         git branch -D stash-branch" &&
519         test $(git ls-files --modified | wc -l) -eq 1
520 '
521
522 test_expect_success 'stash branch complains with no arguments' '
523         test_must_fail git stash branch 2>err &&
524         test_i18ngrep "No branch name specified" err
525 '
526
527 test_expect_success 'stash show format defaults to --stat' '
528         git stash clear &&
529         test_when_finished "git reset --hard HEAD" &&
530         git reset --hard &&
531         echo foo >>file &&
532         git stash &&
533         test_when_finished "git stash drop" &&
534         echo bar >>file &&
535         STASH_ID=$(git stash create) &&
536         git reset --hard &&
537         cat >expected <<-EOF &&
538          file | 1 +
539          1 file changed, 1 insertion(+)
540         EOF
541         git stash show ${STASH_ID} >actual &&
542         test_i18ncmp expected actual
543 '
544
545 test_expect_success 'stash show - stashes on stack, stash-like argument' '
546         git stash clear &&
547         test_when_finished "git reset --hard HEAD" &&
548         git reset --hard &&
549         echo foo >>file &&
550         git stash &&
551         test_when_finished "git stash drop" &&
552         echo bar >>file &&
553         STASH_ID=$(git stash create) &&
554         git reset --hard &&
555         echo "1 0       file" >expected &&
556         git stash show --numstat ${STASH_ID} >actual &&
557         test_cmp expected actual
558 '
559
560 test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
561         git stash clear &&
562         test_when_finished "git reset --hard HEAD" &&
563         git reset --hard &&
564         echo foo >>file &&
565         git stash &&
566         test_when_finished "git stash drop" &&
567         echo bar >>file &&
568         STASH_ID=$(git stash create) &&
569         git reset --hard &&
570         cat >expected <<-EOF &&
571         diff --git a/file b/file
572         index 7601807..935fbd3 100644
573         --- a/file
574         +++ b/file
575         @@ -1 +1,2 @@
576          baz
577         +bar
578         EOF
579         git stash show -p ${STASH_ID} >actual &&
580         test_cmp expected actual
581 '
582
583 test_expect_success 'stash show - no stashes on stack, stash-like argument' '
584         git stash clear &&
585         test_when_finished "git reset --hard HEAD" &&
586         git reset --hard &&
587         echo foo >>file &&
588         STASH_ID=$(git stash create) &&
589         git reset --hard &&
590         echo "1 0       file" >expected &&
591         git stash show --numstat ${STASH_ID} >actual &&
592         test_cmp expected actual
593 '
594
595 test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
596         git stash clear &&
597         test_when_finished "git reset --hard HEAD" &&
598         git reset --hard &&
599         echo foo >>file &&
600         STASH_ID=$(git stash create) &&
601         git reset --hard &&
602         cat >expected <<-EOF &&
603         diff --git a/file b/file
604         index 7601807..71b52c4 100644
605         --- a/file
606         +++ b/file
607         @@ -1 +1,2 @@
608          baz
609         +foo
610         EOF
611         git stash show -p ${STASH_ID} >actual &&
612         test_cmp expected actual
613 '
614
615 test_expect_success 'stash show --patience shows diff' '
616         git reset --hard &&
617         echo foo >>file &&
618         STASH_ID=$(git stash create) &&
619         git reset --hard &&
620         cat >expected <<-EOF &&
621         diff --git a/file b/file
622         index 7601807..71b52c4 100644
623         --- a/file
624         +++ b/file
625         @@ -1 +1,2 @@
626          baz
627         +foo
628         EOF
629         git stash show --patience ${STASH_ID} >actual &&
630         test_cmp expected actual
631 '
632
633 test_expect_success 'drop: fail early if specified stash is not a stash ref' '
634         git stash clear &&
635         test_when_finished "git reset --hard HEAD && git stash clear" &&
636         git reset --hard &&
637         echo foo >file &&
638         git stash &&
639         echo bar >file &&
640         git stash &&
641         test_must_fail git stash drop $(git rev-parse stash@{0}) &&
642         git stash pop &&
643         test bar = "$(cat file)" &&
644         git reset --hard HEAD
645 '
646
647 test_expect_success 'pop: fail early if specified stash is not a stash ref' '
648         git stash clear &&
649         test_when_finished "git reset --hard HEAD && git stash clear" &&
650         git reset --hard &&
651         echo foo >file &&
652         git stash &&
653         echo bar >file &&
654         git stash &&
655         test_must_fail git stash pop $(git rev-parse stash@{0}) &&
656         git stash pop &&
657         test bar = "$(cat file)" &&
658         git reset --hard HEAD
659 '
660
661 test_expect_success 'ref with non-existent reflog' '
662         git stash clear &&
663         echo bar5 >file &&
664         echo bar6 >file2 &&
665         git add file2 &&
666         git stash &&
667         test_must_fail git rev-parse --quiet --verify does-not-exist &&
668         test_must_fail git stash drop does-not-exist &&
669         test_must_fail git stash drop does-not-exist@{0} &&
670         test_must_fail git stash pop does-not-exist &&
671         test_must_fail git stash pop does-not-exist@{0} &&
672         test_must_fail git stash apply does-not-exist &&
673         test_must_fail git stash apply does-not-exist@{0} &&
674         test_must_fail git stash show does-not-exist &&
675         test_must_fail git stash show does-not-exist@{0} &&
676         test_must_fail git stash branch tmp does-not-exist &&
677         test_must_fail git stash branch tmp does-not-exist@{0} &&
678         git stash drop
679 '
680
681 test_expect_success 'invalid ref of the form stash@{n}, n >= N' '
682         git stash clear &&
683         test_must_fail git stash drop stash@{0} &&
684         echo bar5 >file &&
685         echo bar6 >file2 &&
686         git add file2 &&
687         git stash &&
688         test_must_fail git stash drop stash@{1} &&
689         test_must_fail git stash pop stash@{1} &&
690         test_must_fail git stash apply stash@{1} &&
691         test_must_fail git stash show stash@{1} &&
692         test_must_fail git stash branch tmp stash@{1} &&
693         git stash drop
694 '
695
696 test_expect_success 'invalid ref of the form "n", n >= N' '
697         git stash clear &&
698         test_must_fail git stash drop 0 &&
699         echo bar5 >file &&
700         echo bar6 >file2 &&
701         git add file2 &&
702         git stash &&
703         test_must_fail git stash drop 1 &&
704         test_must_fail git stash pop 1 &&
705         test_must_fail git stash apply 1 &&
706         test_must_fail git stash show 1 &&
707         test_must_fail git stash branch tmp 1 &&
708         git stash drop
709 '
710
711 test_expect_success 'valid ref of the form "n", n < N' '
712         git stash clear &&
713         echo bar5 >file &&
714         echo bar6 >file2 &&
715         git add file2 &&
716         git stash &&
717         git stash show 0 &&
718         git stash branch tmp 0 &&
719         git checkout master &&
720         git stash &&
721         git stash apply 0 &&
722         git reset --hard &&
723         git stash pop 0 &&
724         git stash &&
725         git stash drop 0 &&
726         test_must_fail git stash drop
727 '
728
729 test_expect_success 'branch: do not drop the stash if the branch exists' '
730         git stash clear &&
731         echo foo >file &&
732         git add file &&
733         git commit -m initial &&
734         echo bar >file &&
735         git stash &&
736         test_must_fail git stash branch master stash@{0} &&
737         git rev-parse stash@{0} --
738 '
739
740 test_expect_success 'branch: should not drop the stash if the apply fails' '
741         git stash clear &&
742         git reset HEAD~1 --hard &&
743         echo foo >file &&
744         git add file &&
745         git commit -m initial &&
746         echo bar >file &&
747         git stash &&
748         echo baz >file &&
749         test_when_finished "git checkout master" &&
750         test_must_fail git stash branch new_branch stash@{0} &&
751         git rev-parse stash@{0} --
752 '
753
754 test_expect_success 'apply: show same status as git status (relative to ./)' '
755         git stash clear &&
756         echo 1 >subdir/subfile1 &&
757         echo 2 >subdir/subfile2 &&
758         git add subdir/subfile1 &&
759         git commit -m subdir &&
760         (
761                 cd subdir &&
762                 echo x >subfile1 &&
763                 echo x >../file &&
764                 git status >../expect &&
765                 git stash &&
766                 sane_unset GIT_MERGE_VERBOSITY &&
767                 git stash apply
768         ) |
769         sed -e 1d >actual && # drop "Saved..."
770         test_i18ncmp expect actual
771 '
772
773 cat >expect <<EOF
774 diff --git a/HEAD b/HEAD
775 new file mode 100644
776 index 0000000..fe0cbee
777 --- /dev/null
778 +++ b/HEAD
779 @@ -0,0 +1 @@
780 +file-not-a-ref
781 EOF
782
783 test_expect_success 'stash where working directory contains "HEAD" file' '
784         git stash clear &&
785         git reset --hard &&
786         echo file-not-a-ref >HEAD &&
787         git add HEAD &&
788         test_tick &&
789         git stash &&
790         git diff-files --quiet &&
791         git diff-index --cached --quiet HEAD &&
792         test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" &&
793         git diff stash^..stash >output &&
794         test_cmp expect output
795 '
796
797 test_expect_success 'store called with invalid commit' '
798         test_must_fail git stash store foo
799 '
800
801 test_expect_success 'store updates stash ref and reflog' '
802         git stash clear &&
803         git reset --hard &&
804         echo quux >bazzy &&
805         git add bazzy &&
806         STASH_ID=$(git stash create) &&
807         git reset --hard &&
808         test_path_is_missing bazzy &&
809         git stash store -m quuxery $STASH_ID &&
810         test $(git rev-parse stash) = $STASH_ID &&
811         git reflog --format=%H stash| grep $STASH_ID &&
812         git stash pop &&
813         grep quux bazzy
814 '
815
816 test_expect_success 'handle stash specification with spaces' '
817         git stash clear &&
818         echo pig >file &&
819         git stash &&
820         stamp=$(git log -g --format="%cd" -1 refs/stash) &&
821         test_tick &&
822         echo cow >file &&
823         git stash &&
824         git stash apply "stash@{$stamp}" &&
825         grep pig file
826 '
827
828 test_expect_success 'setup stash with index and worktree changes' '
829         git stash clear &&
830         git reset --hard &&
831         echo index >file &&
832         git add file &&
833         echo working >file &&
834         git stash
835 '
836
837 test_expect_success 'stash list implies --first-parent -m' '
838         cat >expect <<-EOF &&
839         stash@{0}
840
841         diff --git a/file b/file
842         index 257cc56..d26b33d 100644
843         --- a/file
844         +++ b/file
845         @@ -1 +1 @@
846         -foo
847         +working
848         EOF
849         git stash list --format=%gd -p >actual &&
850         test_cmp expect actual
851 '
852
853 test_expect_success 'stash list --cc shows combined diff' '
854         cat >expect <<-\EOF &&
855         stash@{0}
856
857         diff --cc file
858         index 257cc56,9015a7a..d26b33d
859         --- a/file
860         +++ b/file
861         @@@ -1,1 -1,1 +1,1 @@@
862         - foo
863          -index
864         ++working
865         EOF
866         git stash list --format=%gd -p --cc >actual &&
867         test_cmp expect actual
868 '
869
870 test_expect_success 'stash is not confused by partial renames' '
871         mv file renamed &&
872         git add renamed &&
873         git stash &&
874         git stash apply &&
875         test_path_is_file renamed &&
876         test_path_is_missing file
877 '
878
879 test_expect_success 'push -m shows right message' '
880         >foo &&
881         git add foo &&
882         git stash push -m "test message" &&
883         echo "stash@{0}: On master: test message" >expect &&
884         git stash list -1 >actual &&
885         test_cmp expect actual
886 '
887
888 test_expect_success 'push -m also works without space' '
889         >foo &&
890         git add foo &&
891         git stash push -m"unspaced test message" &&
892         echo "stash@{0}: On master: unspaced test message" >expect &&
893         git stash list -1 >actual &&
894         test_cmp expect actual
895 '
896
897 test_expect_success 'store -m foo shows right message' '
898         git stash clear &&
899         git reset --hard &&
900         echo quux >bazzy &&
901         git add bazzy &&
902         STASH_ID=$(git stash create) &&
903         git stash store -m "store m" $STASH_ID &&
904         echo "stash@{0}: store m" >expect &&
905         git stash list -1 >actual &&
906         test_cmp expect actual
907 '
908
909 test_expect_success 'store -mfoo shows right message' '
910         git stash clear &&
911         git reset --hard &&
912         echo quux >bazzy &&
913         git add bazzy &&
914         STASH_ID=$(git stash create) &&
915         git stash store -m"store mfoo" $STASH_ID &&
916         echo "stash@{0}: store mfoo" >expect &&
917         git stash list -1 >actual &&
918         test_cmp expect actual
919 '
920
921 test_expect_success 'store --message=foo shows right message' '
922         git stash clear &&
923         git reset --hard &&
924         echo quux >bazzy &&
925         git add bazzy &&
926         STASH_ID=$(git stash create) &&
927         git stash store --message="store message=foo" $STASH_ID &&
928         echo "stash@{0}: store message=foo" >expect &&
929         git stash list -1 >actual &&
930         test_cmp expect actual
931 '
932
933 test_expect_success 'store --message foo shows right message' '
934         git stash clear &&
935         git reset --hard &&
936         echo quux >bazzy &&
937         git add bazzy &&
938         STASH_ID=$(git stash create) &&
939         git stash store --message "store message foo" $STASH_ID &&
940         echo "stash@{0}: store message foo" >expect &&
941         git stash list -1 >actual &&
942         test_cmp expect actual
943 '
944
945 test_expect_success 'push -mfoo uses right message' '
946         >foo &&
947         git add foo &&
948         git stash push -m"test mfoo" &&
949         echo "stash@{0}: On master: test mfoo" >expect &&
950         git stash list -1 >actual &&
951         test_cmp expect actual
952 '
953
954 test_expect_success 'push --message foo is synonym for -mfoo' '
955         >foo &&
956         git add foo &&
957         git stash push --message "test message foo" &&
958         echo "stash@{0}: On master: test message foo" >expect &&
959         git stash list -1 >actual &&
960         test_cmp expect actual
961 '
962
963 test_expect_success 'push --message=foo is synonym for -mfoo' '
964         >foo &&
965         git add foo &&
966         git stash push --message="test message=foo" &&
967         echo "stash@{0}: On master: test message=foo" >expect &&
968         git stash list -1 >actual &&
969         test_cmp expect actual
970 '
971
972 test_expect_success 'push -m shows right message' '
973         >foo &&
974         git add foo &&
975         git stash push -m "test m foo" &&
976         echo "stash@{0}: On master: test m foo" >expect &&
977         git stash list -1 >actual &&
978         test_cmp expect actual
979 '
980
981 test_expect_success 'create stores correct message' '
982         >foo &&
983         git add foo &&
984         STASH_ID=$(git stash create "create test message") &&
985         echo "On master: create test message" >expect &&
986         git show --pretty=%s -s ${STASH_ID} >actual &&
987         test_cmp expect actual
988 '
989
990 test_expect_success 'create with multiple arguments for the message' '
991         >foo &&
992         git add foo &&
993         STASH_ID=$(git stash create test untracked) &&
994         echo "On master: test untracked" >expect &&
995         git show --pretty=%s -s ${STASH_ID} >actual &&
996         test_cmp expect actual
997 '
998
999 test_expect_success 'create in a detached state' '
1000         test_when_finished "git checkout master" &&
1001         git checkout HEAD~1 &&
1002         >foo &&
1003         git add foo &&
1004         STASH_ID=$(git stash create) &&
1005         HEAD_ID=$(git rev-parse --short HEAD) &&
1006         echo "WIP on (no branch): ${HEAD_ID} initial" >expect &&
1007         git show --pretty=%s -s ${STASH_ID} >actual &&
1008         test_cmp expect actual
1009 '
1010
1011 test_expect_success 'stash -- <pathspec> stashes and restores the file' '
1012         >foo &&
1013         >bar &&
1014         git add foo bar &&
1015         git stash push -- foo &&
1016         test_path_is_file bar &&
1017         test_path_is_missing foo &&
1018         git stash pop &&
1019         test_path_is_file foo &&
1020         test_path_is_file bar
1021 '
1022
1023 test_expect_success 'stash -- <pathspec> stashes in subdirectory' '
1024         mkdir sub &&
1025         >foo &&
1026         >bar &&
1027         git add foo bar &&
1028         (
1029                 cd sub &&
1030                 git stash push -- ../foo
1031         ) &&
1032         test_path_is_file bar &&
1033         test_path_is_missing foo &&
1034         git stash pop &&
1035         test_path_is_file foo &&
1036         test_path_is_file bar
1037 '
1038
1039 test_expect_success 'stash with multiple pathspec arguments' '
1040         >foo &&
1041         >bar &&
1042         >extra &&
1043         git add foo bar extra &&
1044         git stash push -- foo bar &&
1045         test_path_is_missing bar &&
1046         test_path_is_missing foo &&
1047         test_path_is_file extra &&
1048         git stash pop &&
1049         test_path_is_file foo &&
1050         test_path_is_file bar &&
1051         test_path_is_file extra
1052 '
1053
1054 test_expect_success 'stash with file including $IFS character' '
1055         >"foo bar" &&
1056         >foo &&
1057         >bar &&
1058         git add foo* &&
1059         git stash push -- "foo b*" &&
1060         test_path_is_missing "foo bar" &&
1061         test_path_is_file foo &&
1062         test_path_is_file bar &&
1063         git stash pop &&
1064         test_path_is_file "foo bar" &&
1065         test_path_is_file foo &&
1066         test_path_is_file bar
1067 '
1068
1069 test_expect_success 'stash with pathspec matching multiple paths' '
1070        echo original >file &&
1071        echo original >other-file &&
1072        git commit -m "two" file other-file &&
1073        echo modified >file &&
1074        echo modified >other-file &&
1075        git stash push -- "*file" &&
1076        echo original >expect &&
1077        test_cmp expect file &&
1078        test_cmp expect other-file &&
1079        git stash pop &&
1080        echo modified >expect &&
1081        test_cmp expect file &&
1082        test_cmp expect other-file
1083 '
1084
1085 test_expect_success 'stash push -p with pathspec shows no changes only once' '
1086         >foo &&
1087         git add foo &&
1088         git commit -m "tmp" &&
1089         git stash push -p foo >actual &&
1090         echo "No local changes to save" >expect &&
1091         git reset --hard HEAD~ &&
1092         test_i18ncmp expect actual
1093 '
1094
1095 test_expect_success 'push <pathspec>: show no changes when there are none' '
1096         >foo &&
1097         git add foo &&
1098         git commit -m "tmp" &&
1099         git stash push foo >actual &&
1100         echo "No local changes to save" >expect &&
1101         git reset --hard HEAD~ &&
1102         test_i18ncmp expect actual
1103 '
1104
1105 test_expect_success 'push: <pathspec> not in the repository errors out' '
1106         >untracked &&
1107         test_must_fail git stash push untracked &&
1108         test_path_is_file untracked
1109 '
1110
1111 test_expect_success 'push: -q is quiet with changes' '
1112         >foo &&
1113         git add foo &&
1114         git stash push -q >output 2>&1 &&
1115         test_must_be_empty output
1116 '
1117
1118 test_expect_success 'push: -q is quiet with no changes' '
1119         git stash push -q >output 2>&1 &&
1120         test_must_be_empty output
1121 '
1122
1123 test_expect_success 'push: -q is quiet even if there is no initial commit' '
1124         git init foo_dir &&
1125         test_when_finished rm -rf foo_dir &&
1126         (
1127                 cd foo_dir &&
1128                 >bar &&
1129                 test_must_fail git stash push -q >output 2>&1 &&
1130                 test_must_be_empty output
1131         )
1132 '
1133
1134 test_expect_success 'untracked files are left in place when -u is not given' '
1135         >file &&
1136         git add file &&
1137         >untracked &&
1138         git stash push file &&
1139         test_path_is_file untracked
1140 '
1141
1142 test_expect_success 'stash without verb with pathspec' '
1143         >"foo bar" &&
1144         >foo &&
1145         >bar &&
1146         git add foo* &&
1147         git stash -- "foo b*" &&
1148         test_path_is_missing "foo bar" &&
1149         test_path_is_file foo &&
1150         test_path_is_file bar &&
1151         git stash pop &&
1152         test_path_is_file "foo bar" &&
1153         test_path_is_file foo &&
1154         test_path_is_file bar
1155 '
1156
1157 test_expect_success 'stash -k -- <pathspec> leaves unstaged files intact' '
1158         git reset &&
1159         >foo &&
1160         >bar &&
1161         git add foo bar &&
1162         git commit -m "test" &&
1163         echo "foo" >foo &&
1164         echo "bar" >bar &&
1165         git stash -k -- foo &&
1166         test "",bar = $(cat foo),$(cat bar) &&
1167         git stash pop &&
1168         test foo,bar = $(cat foo),$(cat bar)
1169 '
1170
1171 test_expect_success 'stash -- <subdir> leaves untracked files in subdir intact' '
1172         git reset &&
1173         >subdir/untracked &&
1174         >subdir/tracked1 &&
1175         >subdir/tracked2 &&
1176         git add subdir/tracked* &&
1177         git stash -- subdir/ &&
1178         test_path_is_missing subdir/tracked1 &&
1179         test_path_is_missing subdir/tracked2 &&
1180         test_path_is_file subdir/untracked &&
1181         git stash pop &&
1182         test_path_is_file subdir/tracked1 &&
1183         test_path_is_file subdir/tracked2 &&
1184         test_path_is_file subdir/untracked
1185 '
1186
1187 test_expect_success 'stash -- <subdir> works with binary files' '
1188         git reset &&
1189         >subdir/untracked &&
1190         >subdir/tracked &&
1191         cp "$TEST_DIRECTORY"/test-binary-1.png subdir/tracked-binary &&
1192         git add subdir/tracked* &&
1193         git stash -- subdir/ &&
1194         test_path_is_missing subdir/tracked &&
1195         test_path_is_missing subdir/tracked-binary &&
1196         test_path_is_file subdir/untracked &&
1197         git stash pop &&
1198         test_path_is_file subdir/tracked &&
1199         test_path_is_file subdir/tracked-binary &&
1200         test_path_is_file subdir/untracked
1201 '
1202
1203 test_expect_success 'stash with user.name and user.email set works' '
1204         test_config user.name "A U Thor" &&
1205         test_config user.email "a.u@thor" &&
1206         git stash
1207 '
1208
1209 test_expect_success 'stash works when user.name and user.email are not set' '
1210         git reset &&
1211         >1 &&
1212         git add 1 &&
1213         echo "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" >expect &&
1214         git stash &&
1215         git show -s --format="%an <%ae>" refs/stash >actual &&
1216         test_cmp expect actual &&
1217         >2 &&
1218         git add 2 &&
1219         test_config user.useconfigonly true &&
1220         test_config stash.usebuiltin true &&
1221         (
1222                 sane_unset GIT_AUTHOR_NAME &&
1223                 sane_unset GIT_AUTHOR_EMAIL &&
1224                 sane_unset GIT_COMMITTER_NAME &&
1225                 sane_unset GIT_COMMITTER_EMAIL &&
1226                 test_unconfig user.email &&
1227                 test_unconfig user.name &&
1228                 test_must_fail git commit -m "should fail" &&
1229                 echo "git stash <git@stash>" >expect &&
1230                 >2 &&
1231                 git stash &&
1232                 git show -s --format="%an <%ae>" refs/stash >actual &&
1233                 test_cmp expect actual
1234         )
1235 '
1236
1237 test_expect_success 'stash --keep-index with file deleted in index does not resurrect it on disk' '
1238         test_commit to-remove to-remove &&
1239         git rm to-remove &&
1240         git stash --keep-index &&
1241         test_path_is_missing to-remove
1242 '
1243
1244 test_expect_success 'stash handles skip-worktree entries nicely' '
1245         test_commit A &&
1246         echo changed >A.t &&
1247         git add A.t &&
1248         git update-index --skip-worktree A.t &&
1249         rm A.t &&
1250         git stash &&
1251
1252         git rev-parse --verify refs/stash:A.t
1253 '
1254
1255 test_done