Subject: [RFC] git stash --snapshot

From: "Randall S. Becker" <[email-masked]>
Date: Thu, 21 Mar 2019 18:58:47 -0400

About two weeks ago there was a discussion about building an undo stack. 
https://public-inbox.org/git/[email-masked]/

it had me thinking about whether a stash --snapshot might be useful. Below
is a conceptual change - by no means even close to complete. This would
allow scripting to wrap critical commands with a "git stash push --snapshot"
without changing the working directory. For symmetry, a "git stash pop
--force" is needed if --include-untracked were used to stash everything in
the first place. It might be more useful also to wait until stash is
converted to C, I suppose. I'm wondering whether to pursue this or drop it.
Thoughts? (and I beg forgiveness for what my mailer might do to the wrapping
of this patch, and I already know the indent is wrong between 329 and 370,
and that the granularity of the --force option is wrong).

diff --git a/git-stash.sh b/git-stash.sh
index 789ce2f41d..7741192980 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -5,12 +5,13 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="list [<options>]
    or: $dashless show [<stash>]
    or: $dashless drop [-q|--quiet] [<stash>]
-   or: $dashless ( pop | apply ) [--index] [-q|--quiet] [<stash>]
+   or: $dashless ( pop | apply ) [--index] [-q|--quiet] [-f|--force]
[<stash>]
    or: $dashless branch <branchname> [<stash>]
    or: $dashless save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
                      [-u|--include-untracked] [-a|--all] [<message>]
    or: $dashless [push [--patch] [-k|--[no-]keep-index] [-q|--quiet]
                       [-u|--include-untracked] [-a|--all] [-m <message>]
+                      [--snapshot]
                       [-- <pathspec>...]]
    or: $dashless clear"

@@ -252,6 +253,7 @@ push_stash () {
        patch_mode=
        untracked=
        stash_msg=
+       snapshot=
        while test $# != 0
        do
                case "$1" in
@@ -286,6 +288,9 @@ push_stash () {
                --message=*)
                        stash_msg=${1#--message=}
                        ;;
+               --snapshot)
+                       snapshot=t
+                       ;;
                --help)
                        show_help
                        ;;
@@ -329,6 +334,8 @@ push_stash () {
        die "$(gettext "Cannot save the current status")"
        say "$(eval_gettext "Saved working directory and index state
\$stash_msg")"

+       if test -z "$snapshot"
+       then
        if test -z "$patch_mode"
        then
                test "$untracked" = "all" && CLEAN_X_OPTION=-x ||
CLEAN_X_OPTION=
@@ -363,6 +370,7 @@ push_stash () {
                        git reset -q -- "$@"
                fi
        fi
+       fi
 }

 save_stash () {
@@ -490,6 +498,7 @@ parse_flags_and_rev()

        FLAGS=
        REV=
+       FORCE_OPTION=
        for opt
        do
                case "$opt" in
@@ -499,6 +508,9 @@ parse_flags_and_rev()
                        --index)
                                INDEX_OPTION=--index
                        ;;
+                       -f|--force)
+                               FORCE_OPTION=--force
+                       ;;
                        --help)
                                show_help
                        ;;
@@ -607,7 +619,7 @@ apply_stash () {
        if test -n "$u_tree"
        then
                GIT_INDEX_FILE="$TMPindex" git read-tree "$u_tree" &&
-               GIT_INDEX_FILE="$TMPindex" git checkout-index --all &&
+               GIT_INDEX_FILE="$TMPindex" git checkout-index --all
$FORCE_OPTION &&
                rm -f "$TMPindex" ||
                die "$(gettext "Could not restore untracked files from stash
entry")"
        fi
@@ -688,7 +700,7 @@ apply_to_branch () {
        set -- --index "$@"
        assert_stash_like "$@"

-       git checkout -b $branch $REV^ &&
+       git checkout -b $branch $FORCE_OPTION $REV^ &&
        apply_stash "$@" && {
                test -z "$IS_STASH_REF" || drop_stash "$@"
        }

Regards,
Randall

-- Brief whoami:
 NonStop developer since approximately 211288444200000000
 UNIX developer since approximately 421664400
-- In my real life, I talk too much.