stash: allow stashes to be referenced by index only

Instead of referencing "stash@{n}" explicitly, make it possible to simply reference as "n". Most users only reference stashes by their position in the stash stack (what I refer to as the "index" here). The syntax for the typical stash (stash@{n}) is slightly annoying and easy to forget, and sometimes difficult to escape properly in a script. Because of this the capability to do things with the stash by simply referencing the index is desirable. This patch includes the superior implementation provided by Øsse Walle (thanks for that), with a slight change to fix a broken test in the test suite. I also merged the test scripts as suggested by Jeff King, and un-wrapped the documentation as suggested by Junio Hamano. Signed-off-by: Aaron M Watson <watsona4@gmail.com> Reviewed-by: Jeff King <peff@peff.net>

Aaron M Watson committed Oct 24, 2016 at 19:40 UTC a56c8f5aab5a6ffdd687de5134883df60cc4c919
3 files changed +50 -3
Documentation/git-stash.txt
+2 -1
@@ -39,7 +39,8 @@ The latest stash you created is stored in `refs/stash`; older
39 stashes are found in the reflog of this reference and can be named using
40 the usual reflog syntax (e.g. `stash@{0}` is the most recently
41 created stash, `stash@{1}` is the one before it, `stash@{2.hours.ago}`
42 -is also possible).
42 +is also possible). Stashes may also be referenced by specifying just the
43 +stash index (e.g. the integer `n` is equivalent to `stash@{n}`).
44
45 OPTIONS
46 -------
git-stash.sh
+13 -2
@@ -384,9 +384,8 @@ parse_flags_and_rev()
384 i_tree=
385 u_tree=
386
387 - REV=$(git rev-parse --no-flags --symbolic --sq "$@") || exit 1
388 -
387 FLAGS=
388 + REV=
389 for opt
390 do
391 case "$opt" in
@@ -404,6 +403,9 @@ parse_flags_and_rev()
403 die "$(eval_gettext "unknown option: \$opt")"
404 FLAGS="${FLAGS}${FLAGS:+ }$opt"
405 ;;
406 + *)
407 + REV="${REV}${REV:+ }'$opt'"
408 + ;;
409 esac
410 done
411
@@ -422,6 +424,15 @@ parse_flags_and_rev()
424 ;;
425 esac
426
427 + case "$1" in
428 + *[!0-9]*)
429 + :
430 + ;;
431 + *)
432 + set -- "${ref_stash}@{$1}"
433 + ;;
434 + esac
435 +
436 REV=$(git rev-parse --symbolic --verify --quiet "$1") || {
437 reference="$1"
438 die "$(eval_gettext "\$reference is not a valid reference")"
t/t3903-stash.sh
+35
@@ -131,6 +131,26 @@ test_expect_success 'drop middle stash' '
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 &&
@@ -604,6 +624,21 @@ test_expect_success 'invalid ref of the form stash@{n}, n >= N' '
624 git stash drop
625 '
626
627 +test_expect_success 'invalid ref of the form "n", n >= N' '
628 + git stash clear &&
629 + test_must_fail git stash drop 0 &&
630 + echo bar5 >file &&
631 + echo bar6 >file2 &&
632 + git add file2 &&
633 + git stash &&
634 + test_must_fail git stash drop 1 &&
635 + test_must_fail git stash pop 1 &&
636 + test_must_fail git stash apply 1 &&
637 + test_must_fail git stash show 1 &&
638 + test_must_fail git stash branch tmp 1 &&
639 + git stash drop
640 +'
641 +
642 test_expect_success 'stash branch should not drop the stash if the branch exists' '
643 git stash clear &&
644 echo foo >file &&