diff --git a/Documentation/git-stash.adoc b/Documentation/git-stash.adoc index 235d57ddd8f5d1..c379062110cad2 100644 --- a/Documentation/git-stash.adoc +++ b/Documentation/git-stash.adoc @@ -21,7 +21,7 @@ git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | -- git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet] [-u | --include-untracked] [-a | --all] [] git stash clear -git stash create [] +git stash create [-u | --include-untracked] [] git stash store [(-m | --message) ] [-q | --quiet] git stash export (--print | --to-ref ) [...] git stash import @@ -140,10 +140,12 @@ with no conflicts. `drop [-q | --quiet] []`:: Remove a single stash entry from the list of stash entries. -`create`:: +`create [-u | --include-untracked]`:: Create a stash entry (which is a regular commit object) and return its object name, without storing it anywhere in the ref namespace. + If the `--include-untracked` option is used, all untracked files are + also included in the stash entry. This is intended to be useful for scripts. It is probably not the command you want to use; see "push" above. @@ -181,6 +183,9 @@ up with `git clean`. all untracked files are also stashed and then cleaned up with `git clean`. + +When used with the `create` command, all untracked files are also included +in the stash entry. ++ When used with the `show` command, show the untracked files in the stash entry as part of the diff. diff --git a/builtin/stash.c b/builtin/stash.c index 95c5005b0b2197..419f70ea39a228 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -58,7 +58,7 @@ N_("git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]\n" \ " [-u | --include-untracked] [-a | --all] []") #define BUILTIN_STASH_CREATE_USAGE \ - N_("git stash create []") + N_("git stash create [-u | --include-untracked] []") #define BUILTIN_STASH_EXPORT_USAGE \ N_("git stash export (--print | --to-ref ) [...]") #define BUILTIN_STASH_IMPORT_USAGE \ @@ -118,6 +118,11 @@ static const char * const git_stash_clear_usage[] = { NULL }; +static const char * const git_stash_create_usage[] = { + BUILTIN_STASH_CREATE_USAGE, + NULL +}; + static const char * const git_stash_store_usage[] = { BUILTIN_STASH_STORE_USAGE, NULL @@ -1570,22 +1575,30 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b return ret; } -static int create_stash(int argc, const char **argv, const char *prefix UNUSED, +static int create_stash(int argc, const char **argv, const char *prefix, struct repository *repo UNUSED) { int ret; + int include_untracked = 0; + struct option options[] = { + OPT_BOOL('u', "include-untracked", &include_untracked, + N_("include untracked files")), + OPT_END() + }; + struct strbuf stash_msg_buf = STRBUF_INIT; struct stash_info info = STASH_INFO_INIT; struct pathspec ps; - /* Starting with argv[1], since argv[0] is "create" */ - strbuf_join_argv(&stash_msg_buf, argc - 1, ++argv, ' '); + argc = parse_options(argc, argv, prefix, options, git_stash_create_usage, 0); + + strbuf_join_argv(&stash_msg_buf, argc, argv, ' '); memset(&ps, 0, sizeof(ps)); - if (!check_changes_tracked_files(&ps)) + if (!include_untracked && !check_changes_tracked_files(&ps)) return 0; - ret = do_create_stash(&ps, &stash_msg_buf, 0, 0, NULL, 0, &info, + ret = do_create_stash(&ps, &stash_msg_buf, include_untracked, 0, NULL, 0, &info, NULL, 0); if (!ret) printf_ln("%s", oid_to_hex(&info.w_commit)); diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 70879941c22f8c..4e0243e3154469 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -639,6 +639,39 @@ test_expect_success 'stash create - no changes' ' test_must_be_empty actual ' +test_expect_success 'stash create with --include-untracked' ' + test_when_finished "git reset --hard && git clean -fd" && + test_commit stash-create-untracked-1 file1 committed && + echo staged >file2 && + git add file2 && + echo unstaged >file3 && + echo untracked >untracked_file && + STASH_ID=$(git stash create --include-untracked "test message") && + git cat-file -p $STASH_ID >stash_commit && + grep "test message" stash_commit && + grep parent stash_commit >parents && + test_line_count = 3 parents && + UNTRACKED_TREE=$(git rev-parse $STASH_ID^3^{tree}) && + git ls-tree $UNTRACKED_TREE >files && + grep untracked_file files && + test_path_is_file untracked_file +' + +test_expect_success 'stash create without --include-untracked does not include untracked files' ' + test_when_finished "git reset --hard && git clean -fd" && + test_commit stash-create-no-untracked-1 file4 committed && + echo staged >file5 && + git add file5 && + echo unstaged >file6 && + echo untracked >untracked_file2 && + STASH_ID=$(git stash create "test message") && + git cat-file -p $STASH_ID >stash_commit && + grep "test message" stash_commit && + grep parent stash_commit >parents && + test_line_count = 2 parents && + test_path_is_file untracked_file2 +' + test_expect_success 'stash branch - no stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" &&