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