Merge branch 'lb/status-stash-count'

"git status" learned to optionally give how many stash entries the
user has in its output.

* lb/status-stash-count:
  glossary: define 'stash entry'
  status: add optional stash count information
  stash: update documentation to use 'stash entry'
This commit is contained in:
Junio C Hamano 2017-06-26 14:09:29 -07:00
commit 849b44cdf1
12 changed files with 115 additions and 38 deletions

View File

@ -2623,7 +2623,7 @@ rebase.autoSquash::
If set to true enable `--autosquash` option by default. If set to true enable `--autosquash` option by default.
rebase.autoStash:: rebase.autoStash::
When set to true, automatically create a temporary stash When set to true, automatically create a temporary stash entry
before the operation begins, and apply it after the operation before the operation begins, and apply it after the operation
ends. This means that you can run rebase on a dirty worktree. ends. This means that you can run rebase on a dirty worktree.
However, use with care: the final stash application after a However, use with care: the final stash application after a
@ -2995,6 +2995,11 @@ status.displayCommentPrefix::
behavior of linkgit:git-status[1] in Git 1.8.4 and previous. behavior of linkgit:git-status[1] in Git 1.8.4 and previous.
Defaults to false. Defaults to false.
status.showStash::
If set to true, linkgit:git-status[1] will display the number of
entries currently stashed away.
Defaults to false.
status.showUntrackedFiles:: status.showUntrackedFiles::
By default, linkgit:git-status[1] and linkgit:git-commit[1] show By default, linkgit:git-status[1] and linkgit:git-commit[1] show
files which are not currently tracked by Git. Directories which files which are not currently tracked by Git. Directories which
@ -3032,12 +3037,12 @@ status.submoduleSummary::
stash.showPatch:: stash.showPatch::
If this is set to true, the `git stash show` command without an If this is set to true, the `git stash show` command without an
option will show the stash in patch form. Defaults to false. option will show the stash entry in patch form. Defaults to false.
See description of 'show' command in linkgit:git-stash[1]. See description of 'show' command in linkgit:git-stash[1].
stash.showStat:: stash.showStat::
If this is set to true, the `git stash show` command without an If this is set to true, the `git stash show` command without an
option will show diffstat of the stash. Defaults to true. option will show diffstat of the stash entry. Defaults to true.
See description of 'show' command in linkgit:git-stash[1]. See description of 'show' command in linkgit:git-stash[1].
submodule.<name>.url:: submodule.<name>.url::

View File

@ -131,7 +131,7 @@ unless you have read linkgit:git-rebase[1] carefully.
--autostash:: --autostash::
--no-autostash:: --no-autostash::
Before starting rebase, stash local modifications away (see Before starting rebase, stash local modifications away (see
linkgit:git-stash[1]) if needed, and apply the stash when linkgit:git-stash[1]) if needed, and apply the stash entry when
done. `--no-autostash` is useful to override the `rebase.autoStash` done. `--no-autostash` is useful to override the `rebase.autoStash`
configuration variable (see linkgit:git-config[1]). configuration variable (see linkgit:git-config[1]).
+ +

View File

@ -446,7 +446,7 @@ used to override and disable this setting.
--autostash:: --autostash::
--no-autostash:: --no-autostash::
Automatically create a temporary stash before the operation Automatically create a temporary stash entry before the operation
begins, and apply it after the operation ends. This means begins, and apply it after the operation ends. This means
that you can run rebase on a dirty worktree. However, use that you can run rebase on a dirty worktree. However, use
with care: the final stash application after a successful with care: the final stash application after a successful

View File

@ -51,18 +51,18 @@ OPTIONS
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]:: save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]:: push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
Save your local modifications to a new 'stash' and roll them Save your local modifications to a new 'stash entry' and roll them
back to HEAD (in the working tree and in the index). back to HEAD (in the working tree and in the index).
The <message> part is optional and gives The <message> part is optional and gives
the description along with the stashed state. the description along with the stashed state.
+ +
For quickly making a snapshot, you can omit "push". In this mode, For quickly making a snapshot, you can omit "push". In this mode,
non-option arguments are not allowed to prevent a misspelled non-option arguments are not allowed to prevent a misspelled
subcommand from making an unwanted stash. The two exceptions to this subcommand from making an unwanted stash entry. The two exceptions to this
are `stash -p` which acts as alias for `stash push -p` and pathspecs, are `stash -p` which acts as alias for `stash push -p` and pathspecs,
which are allowed after a double hyphen `--` for disambiguation. which are allowed after a double hyphen `--` for disambiguation.
+ +
When pathspec is given to 'git stash push', the new stash records the When pathspec is given to 'git stash push', the new stash entry records the
modified states only for the files that match the pathspec. The index 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 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 HEAD only for these files, too, leaving files that do not match the
@ -89,10 +89,10 @@ The `--patch` option implies `--keep-index`. You can use
list [<options>]:: list [<options>]::
List the stashes that you currently have. Each 'stash' is listed List the stash entries that you currently have. Each 'stash entry' is
with its name (e.g. `stash@{0}` is the latest stash, `stash@{1}` is listed with its name (e.g. `stash@{0}` is the latest entry, `stash@{1}` is
the one before, etc.), the name of the branch that was current when the the one before, etc.), the name of the branch that was current when the
stash was made, and a short description of the commit the stash was entry was made, and a short description of the commit the entry was
based on. based on.
+ +
---------------------------------------------------------------- ----------------------------------------------------------------
@ -105,11 +105,12 @@ command to control what is shown and how. See linkgit:git-log[1].
show [<stash>]:: show [<stash>]::
Show the changes recorded in the stash as a diff between the Show the changes recorded in the stash entry as a diff between the
stashed state and its original parent. When no `<stash>` is given, stashed contents and the commit back when the stash entry was first
shows the latest one. By default, the command shows the diffstat, but created. When no `<stash>` is given, it shows the latest one.
it will accept any format known to 'git diff' (e.g., `git stash show By default, the command shows the diffstat, but it will accept any
-p stash@{1}` to view the second most recent stash in patch form). format known to 'git diff' (e.g., `git stash show -p stash@{1}`
to view the second most recent entry in patch form).
You can use stash.showStat and/or stash.showPatch config variables You can use stash.showStat and/or stash.showPatch config variables
to change the default behavior. to change the default behavior.
@ -149,26 +150,27 @@ branch <branchname> [<stash>]::
+ +
This is useful if the branch on which you ran `git stash save` has This is useful if the branch on which you ran `git stash save` has
changed enough that `git stash apply` fails due to conflicts. Since changed enough that `git stash apply` fails due to conflicts. Since
the stash is applied on top of the commit that was HEAD at the time the stash entry is applied on top of the commit that was HEAD at the
`git stash` was run, it restores the originally stashed state with time `git stash` was run, it restores the originally stashed state
no conflicts. with no conflicts.
clear:: clear::
Remove all the stashed states. Note that those states will then Remove all the stash entries. Note that those entries will then
be subject to pruning, and may be impossible to recover (see be subject to pruning, and may be impossible to recover (see
'Examples' below for a possible strategy). 'Examples' below for a possible strategy).
drop [-q|--quiet] [<stash>]:: drop [-q|--quiet] [<stash>]::
Remove a single stashed state from the stash list. When no `<stash>` Remove a single stash entry from the list of stash entries.
is given, it removes the latest one. i.e. `stash@{0}`, otherwise When no `<stash>` is given, it removes the latest one.
`<stash>` must be a valid stash log reference of the form i.e. `stash@{0}`, otherwise `<stash>` must be a valid stash
`stash@{<revision>}`. log reference of the form `stash@{<revision>}`.
create:: create::
Create a stash (which is a regular commit object) and return its Create a stash entry (which is a regular commit object) and
object name, without storing it anywhere in the ref namespace. return its object name, without storing it anywhere in the ref
namespace.
This is intended to be useful for scripts. It is probably not This is intended to be useful for scripts. It is probably not
the command you want to use; see "save" above. the command you want to use; see "save" above.
@ -182,10 +184,10 @@ store::
DISCUSSION DISCUSSION
---------- ----------
A stash is represented as a commit whose tree records the state of the A stash entry is represented as a commit whose tree records the state
working directory, and its first parent is the commit at `HEAD` when of the working directory, and its first parent is the commit at `HEAD`
the stash was created. The tree of the second parent records the when the entry was created. The tree of the second parent records the
state of the index when the stash is made, and it is made a child of state of the index when the entry is made, and it is made a child of
the `HEAD` commit. The ancestry graph looks like this: the `HEAD` commit. The ancestry graph looks like this:
.----W .----W
@ -269,12 +271,12 @@ $ edit/build/test remaining parts
$ git commit foo -m 'Remaining parts' $ git commit foo -m 'Remaining parts'
---------------------------------------------------------------- ----------------------------------------------------------------
Recovering stashes that were cleared/dropped erroneously:: Recovering stash entries that were cleared/dropped erroneously::
If you mistakenly drop or clear stashes, they cannot be recovered If you mistakenly drop or clear stash entries, they cannot be recovered
through the normal safety mechanisms. However, you can try the through the normal safety mechanisms. However, you can try the
following incantation to get a list of stashes that are still in your following incantation to get a list of stash entries that are still in
repository, but not reachable any more: your repository, but not reachable any more:
+ +
---------------------------------------------------------------- ----------------------------------------------------------------
git fsck --unreachable | git fsck --unreachable |

View File

@ -32,6 +32,9 @@ OPTIONS
--branch:: --branch::
Show the branch and tracking info even in short-format. Show the branch and tracking info even in short-format.
--show-stash::
Show the number of entries currently stashed away.
--porcelain[=<version>]:: --porcelain[=<version>]::
Give the output in an easy-to-parse format for scripts. Give the output in an easy-to-parse format for scripts.
This is similar to the short output, but will remain stable This is similar to the short output, but will remain stable

View File

@ -194,7 +194,7 @@ different things.
* The `--index` option is used to ask a command that * The `--index` option is used to ask a command that
usually works on files in the working tree to *also* usually works on files in the working tree to *also*
affect the index. For example, `git stash apply` usually affect the index. For example, `git stash apply` usually
merges changes recorded in a stash to the working tree, merges changes recorded in a stash entry to the working tree,
but with the `--index` option, it also merges changes to but with the `--index` option, it also merges changes to
the index as well. the index as well.

View File

@ -570,6 +570,10 @@ The most notable example is `HEAD`.
is created by giving the `--depth` option to linkgit:git-clone[1], and is created by giving the `--depth` option to linkgit:git-clone[1], and
its history can be later deepened with linkgit:git-fetch[1]. its history can be later deepened with linkgit:git-fetch[1].
[[def_stash]]stash entry::
An <<def_object,object>> used to temporarily store the contents of a
<<def_dirty,dirty>> working directory and the index for future reuse.
[[def_submodule]]submodule:: [[def_submodule]]submodule::
A <<def_repository,repository>> that holds the history of a A <<def_repository,repository>> that holds the history of a
separate project inside another repository (the latter of separate project inside another repository (the latter of

View File

@ -1297,6 +1297,10 @@ static int git_status_config(const char *k, const char *v, void *cb)
status_deferred_config.show_branch = git_config_bool(k, v); status_deferred_config.show_branch = git_config_bool(k, v);
return 0; return 0;
} }
if (!strcmp(k, "status.showstash")) {
s->show_stash = git_config_bool(k, v);
return 0;
}
if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) { if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
s->use_color = git_config_colorbool(k, v); s->use_color = git_config_colorbool(k, v);
return 0; return 0;
@ -1345,6 +1349,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
N_("show status concisely"), STATUS_FORMAT_SHORT), N_("show status concisely"), STATUS_FORMAT_SHORT),
OPT_BOOL('b', "branch", &s.show_branch, OPT_BOOL('b', "branch", &s.show_branch,
N_("show branch information")), N_("show branch information")),
OPT_BOOL(0, "show-stash", &s.show_stash,
N_("show stash information")),
{ OPTION_CALLBACK, 0, "porcelain", &status_format, { OPTION_CALLBACK, 0, "porcelain", &status_format,
N_("version"), N_("machine-readable output"), N_("version"), N_("machine-readable output"),
PARSE_OPT_OPTARG, opt_parse_porcelain }, PARSE_OPT_OPTARG, opt_parse_porcelain },

View File

@ -484,7 +484,7 @@ parse_flags_and_rev()
case $# in case $# in
0) 0)
have_stash || die "$(gettext "No stash found.")" have_stash || die "$(gettext "No stash entries found.")"
set -- ${ref_stash}@{0} set -- ${ref_stash}@{0}
;; ;;
1) 1)
@ -576,7 +576,7 @@ apply_stash () {
GIT_INDEX_FILE="$TMPindex" git-read-tree "$u_tree" && 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 &&
rm -f "$TMPindex" || rm -f "$TMPindex" ||
die "$(gettext "Could not restore untracked files from stash")" die "$(gettext "Could not restore untracked files from stash entry")"
fi fi
eval " eval "
@ -630,7 +630,7 @@ pop_stash() {
drop_stash "$@" drop_stash "$@"
else else
status=$? status=$?
say "$(gettext "The stash is kept in case you need it again.")" say "$(gettext "The stash entry is kept in case you need it again.")"
exit $status exit $status
fi fi
} }

View File

@ -1608,4 +1608,36 @@ test_expect_success 'git commit -m will commit a staged but ignored submodule' '
git config -f .gitmodules --remove-section submodule.subname git config -f .gitmodules --remove-section submodule.subname
' '
test_expect_success 'show stash info with "--show-stash"' '
git reset --hard &&
git stash clear &&
echo 1 >file &&
git add file &&
git stash &&
git status >expected_default &&
git status --show-stash >expected_with_stash &&
test_i18ngrep "^Your stash currently has 1 entry$" expected_with_stash
'
test_expect_success 'no stash info with "--show-stash --no-show-stash"' '
git status --show-stash --no-show-stash >expected_without_stash &&
test_cmp expected_default expected_without_stash
'
test_expect_success '"status.showStash=false" weaker than "--show-stash"' '
git -c status.showStash=false status --show-stash >actual &&
test_cmp expected_with_stash actual
'
test_expect_success '"status.showStash=true" weaker than "--no-show-stash"' '
git -c status.showStash=true status --no-show-stash >actual &&
test_cmp expected_without_stash actual
'
test_expect_success 'no additionnal info if no stash entries' '
git stash clear &&
git -c status.showStash=true status >actual &&
test_cmp expected_without_stash actual
'
test_done test_done

View File

@ -137,6 +137,7 @@ void wt_status_prepare(struct wt_status *s)
s->untracked.strdup_strings = 1; s->untracked.strdup_strings = 1;
s->ignored.strdup_strings = 1; s->ignored.strdup_strings = 1;
s->show_branch = -1; /* unspecified */ s->show_branch = -1; /* unspecified */
s->show_stash = 0;
s->display_comment_prefix = 0; s->display_comment_prefix = 0;
} }
@ -801,6 +802,27 @@ static void wt_longstatus_print_changed(struct wt_status *s)
wt_longstatus_print_trailer(s); wt_longstatus_print_trailer(s);
} }
static int stash_count_refs(struct object_id *ooid, struct object_id *noid,
const char *email, timestamp_t timestamp, int tz,
const char *message, void *cb_data)
{
int *c = cb_data;
(*c)++;
return 0;
}
static void wt_longstatus_print_stash_summary(struct wt_status *s)
{
int stash_count = 0;
for_each_reflog_ent("refs/stash", stash_count_refs, &stash_count);
if (stash_count > 0)
status_printf_ln(s, GIT_COLOR_NORMAL,
Q_("Your stash currently has %d entry",
"Your stash currently has %d entries", stash_count),
stash_count);
}
static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncommitted) static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncommitted)
{ {
struct child_process sm_summary = CHILD_PROCESS_INIT; struct child_process sm_summary = CHILD_PROCESS_INIT;
@ -1642,6 +1664,8 @@ static void wt_longstatus_print(struct wt_status *s)
} else } else
printf(_("nothing to commit, working tree clean\n")); printf(_("nothing to commit, working tree clean\n"));
} }
if(s->show_stash)
wt_longstatus_print_stash_summary(s);
} }
static void wt_shortstatus_unmerged(struct string_list_item *it, static void wt_shortstatus_unmerged(struct string_list_item *it,

View File

@ -77,6 +77,7 @@ struct wt_status {
unsigned colopts; unsigned colopts;
int null_termination; int null_termination;
int show_branch; int show_branch;
int show_stash;
int hints; int hints;
enum wt_status_format status_format; enum wt_status_format status_format;