stash: introduce 'stash save --keep-index' option

'git stash save' saves local modifications to a new stash, and runs 'git
reset --hard' to revert them to a clean index and work tree.  When the
'--keep-index' option is specified, after that 'git reset --hard' the
previous contents of the index is restored and the work tree is updated
to match the index.  This option is useful if the user wants to commit
only parts of his local modifications, but wants to test those parts
before committing.

Also add support for the completion of the new option, and add an
example use case to the documentation.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/git-stash.sh b/git-stash.sh
index 4938ade..92531a2 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -86,6 +86,13 @@
 }
 
 save_stash () {
+	keep_index=
+	case "$1" in
+	--keep-index)
+		keep_index=t
+		shift
+	esac
+
 	stash_msg="$1"
 
 	if no_changes
@@ -104,6 +111,13 @@
 	git update-ref -m "$stash_msg" $ref_stash $w_commit ||
 		die "Cannot save the current status"
 	printf 'Saved working directory and index state "%s"\n' "$stash_msg"
+
+	git reset --hard
+
+	if test -n "$keep_index" && test -n $i_tree
+	then
+		git read-tree --reset -u $i_tree
+	fi
 }
 
 have_stash () {
@@ -153,7 +167,8 @@
 		die "$*: no valid stashed state found"
 
 	unstashed_index_tree=
-	if test -n "$unstash_index" && test "$b_tree" != "$i_tree"
+	if test -n "$unstash_index" && test "$b_tree" != "$i_tree" &&
+			test "$c_tree" != "$i_tree"
 	then
 		git diff-tree --binary $s^2^..$s^2 | git apply --cached
 		test $? -ne 0 &&
@@ -235,7 +250,7 @@
 	;;
 save)
 	shift
-	save_stash "$*" && git-reset --hard
+	save_stash "$*"
 	;;
 apply)
 	shift
@@ -268,8 +283,7 @@
 	if test $# -eq 0
 	then
 		save_stash &&
-		echo '(To restore them type "git stash apply")' &&
-		git-reset --hard
+		echo '(To restore them type "git stash apply")'
 	else
 		usage
 	fi