While working on a repository, it's often helpful to stash the changes
of a single or multiple files, and leave others alone. Unfortunately
git currently offers no such option. git stash -p can be used to work
around this, but it's often impractical when there are a lot of changes
over multiple files.
Allow 'git stash push' to take pathspec to specify which paths to stash.
Helped-by: Junio C Hamano
Signed-off-by: Thomas Gummerer
---
Documentation/git-stash.txt| 11 ++
git-stash.sh | 30 ---
t/t3903-stash.sh | 42 ++
t/t3905-stash-include-untracked.sh | 26 +++
4 files changed, 102 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index a138ed6a24..be55e456fa 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -15,9 +15,13 @@ SYNOPSIS
'git stash' branch []
'git stash' [save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] []]
+'git stash' push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
+[-u|--include-untracked] [-a|--all] [-m|--message ]]
+[--] [...]
'git stash' clear
'git stash' create []
'git stash' create [-m ] [-u|--include-untracked ]
+[-- ...]
'git stash' store [-m|--message ] [-q|--quiet]
DESCRIPTION
@@ -47,6 +51,7 @@ OPTIONS
---
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all]
[-q|--quiet] []::
+push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all]
[-q|--quiet] [-m|--message ] [--] [...]::
Save your local modifications to a new 'stash' and roll them
back to HEAD (in the working tree and in the index).
@@ -56,6 +61,12 @@ save [-p|--patch] [-k|--[no-]keep-index]
[-u|--include-untracked] [-a|--all] [-q
only does not trigger this action to prevent a misspelled
subcommand from making an unwanted stash.
+
+When pathspec is given to 'git stash push', the new stash records the
+modified states only for the files that match the pathspec. The index
+entries and working tree files are then rolled back to the state in
+HEAD only for these files, too, leaving files that do not match the
+pathspec intact.
++
If the `--keep-index` option is used, all changes already added to the
index are left intact.
+
diff --git a/git-stash.sh b/git-stash.sh
index 33b2d0384c..46367d40aa 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -41,7 +41,7 @@ no_changes () {
untracked_files () {
excl_opt=--exclude-standard
test "$untracked" = "all" && excl_opt=
- git ls-files -o -z $excl_opt
+ git ls-files -o -z $excl_opt -- "$@"
}
clear_stash () {
@@ -72,6 +72,11 @@ create_stash () {
untracked="$1"
new_style=t
;;
+ --)
+ shift
+ new_style=t
+ break
+ ;;
*)
if test -n "$new_style"
then
@@ -99,6 +104,10 @@ create_stash () {
if test -z "$new_style"
then
stash_msg="$*"
+ while test $# != 0
+ do
+ shift
+ done
fi
git update-index -q --refresh
@@ -134,7 +143,7 @@ create_stash () {
# Untracked files are stored by themselves in a parentless
commit, for
# ease of unpacking later.
u_commit=$(
- untracked_files | (
+ untracked_files "$@" | (
GIT_INDEX_FILE="$TMPindex" &&
export GIT_INDEX_FILE &&
rm -f "$TMPindex" &&
@@ -157,7 +166,7 @@ create_stash () {
git read-tree --index-output="$TMPindex" -m $i_tree &&
GIT_INDEX_FILE="$TMPindex" &&
export GIT_INDEX_FILE &&
- git diff-index --name-only -z HEAD --
>"$TMP-stagenames" &&
+ git diff-index --name-only -z HEAD -- "$@"
>"$TMP-stagenames" &&
git update-index -z --add --remove --stdin
<"$TMP-stagenames" &&
git write-tree &&
rm -f "$TMPindex"
@@ -171,7 +180,7 @@ create_stash () {
# find out what the user wants
GIT_INDEX_FILE="$TMP-index" \
- git add--interactive --patch=stash -- &&
+ git add--interactive --patch=stash -- "$@" &&
# state of the working tree
w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) ||
@@ -307,18 +316,25 @@ push_stash () {
git reflog