From: "Miroma via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Karthik Nayak <karthik.188@gmail.com>,
Miroma <its.miroma@proton.me>, Miroma <its.miroma@proton.me>
Subject: [PATCH v2] stash: show correct entries count
Date: Thu, 09 Oct 2025 11:03:03 +0000 [thread overview]
Message-ID: <pull.2067.v2.git.git.1760007783388.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2067.git.git.1759750539721.gitgitgadget@gmail.com>
From: Miroma <its.miroma@proton.me>
Currently, 'stash apply' internally calls 'status' to show a summary of
what the command did. This also happens with 'stash pop', which roughly
corresponds to 'apply' + 'drop'.
When the configuration 'status.showStash' is set, 'status' shows a count
of stashed entries. This leads to the following, confusing, output:
```sh
$ # assuming there are two stashed entries
$ git stash pop
...
Your stash currently has 2 entries
Dropped refs/stash@{0} (abc123...)
$ # when actually...
$ git status --show-stash
...
Your stash currently has 1 entry
```
This patch changes the output format to the following, no matter the
value of 'status.showStash':
```sh
$ # assuming there's a stashed entry
$ git stash pop
...
Dropped refs/stash@{0} (abc123...)
Your stash now has 0 entries
```
This new output is only shown if the stash count has changed, which can
happen with the following subcommands:
'drop', 'pop', 'branch', 'store', 'push', 'save'.
Helped-by: Karthik Nayak <karthik.188@gmail.com>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Miroma <its.miroma@proton.me>
---
stash: show correct entries count
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2067%2Fits-miroma%2Fstash-no-status-showStash-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2067/its-miroma/stash-no-status-showStash-v2
Pull-Request: https://github.com/git/git/pull/2067
Range-diff vs v1:
1: 32a45cf3d2 < -: ---------- stash: don't show irrelevant entry count in status
-: ---------- > 1: 1118bd68ac stash: show correct entries count
builtin/stash.c | 31 ++++++++++++++++++--
t/t3903-stash.sh | 75 ++++++++++++++++++++++++++++--------------------
wt-status.c | 2 +-
wt-status.h | 1 +
4 files changed, 75 insertions(+), 34 deletions(-)
diff --git a/builtin/stash.c b/builtin/stash.c
index 1977e50df2..1bee391fb2 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -32,6 +32,7 @@
#include "add-interactive.h"
#include "oid-array.h"
#include "commit.h"
+#include "wt-status.h"
#define INCLUDE_ALL_FILES 2
@@ -585,6 +586,20 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
die(_("could not write index"));
}
+static int previous_stash_count = -1;
+
+static void print_stash_status(bool quiet)
+{
+ int stash_count;
+ stash_count = count_stash_entries();
+
+ if (quiet || stash_count == previous_stash_count || previous_stash_count == -1)
+ return;
+
+ printf_ln(Q_("Your stash now has %d entry",
+ "Your stash now has %d entries", stash_count), stash_count);
+}
+
static int do_apply_stash(const char *prefix, struct stash_info *info,
int index, int quiet)
{
@@ -705,7 +720,7 @@ restore_untracked:
absolute_path(repo_get_work_tree(the_repository)));
strvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT"=%s",
absolute_path(repo_get_git_dir(the_repository)));
- strvec_push(&cp.args, "status");
+ strvec_pushl(&cp.args, "status", "--no-show-stash", NULL);
run_command(&cp);
}
@@ -756,6 +771,8 @@ static int reflog_is_empty(const char *refname)
static int do_drop_stash(struct stash_info *info, int quiet)
{
+ previous_stash_count = count_stash_entries();
+
if (!reflog_delete(info->revision.buf,
EXPIRE_REFLOGS_REWRITE | EXPIRE_REFLOGS_UPDATE_REF,
0)) {
@@ -805,6 +822,8 @@ static int drop_stash(int argc, const char **argv, const char *prefix,
goto cleanup;
ret = do_drop_stash(&info, quiet);
+ print_stash_status(quiet);
+
cleanup:
free_stash_info(&info);
return ret;
@@ -836,6 +855,8 @@ static int pop_stash(int argc, const char **argv, const char *prefix,
else
ret = do_drop_stash(&info, quiet);
+ print_stash_status(quiet);
+
cleanup:
free_stash_info(&info);
return ret;
@@ -875,6 +896,8 @@ static int branch_stash(int argc, const char **argv, const char *prefix,
if (!ret && info.is_stash_ref)
ret = do_drop_stash(&info, 0);
+ print_stash_status(0);
+
cleanup:
free_stash_info(&info);
return ret;
@@ -1062,6 +1085,7 @@ static int do_store_stash(const struct object_id *w_commit, const char *stash_ms
struct stash_info info;
char revision[GIT_MAX_HEXSZ];
+ previous_stash_count = count_stash_entries();
oid_to_hex_r(revision, w_commit);
assert_stash_like(&info, revision);
@@ -1119,6 +1143,7 @@ static int store_stash(int argc, const char **argv, const char *prefix,
}
ret = do_store_stash(&obj, stash_msg, quiet);
+ print_stash_status(quiet);
out:
object_context_release(&dummy);
@@ -1914,6 +1939,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
&add_p_opt, include_untracked, only_staged);
+ print_stash_status(quiet);
clear_pathspec(&ps);
free(pathspec_from_file);
@@ -1982,6 +2008,7 @@ static int save_stash(int argc, const char **argv, const char *prefix,
ret = do_push_stash(&ps, stash_msg, quiet, keep_index,
patch_mode, &add_p_opt, include_untracked,
only_staged);
+ print_stash_status(quiet);
strbuf_release(&stash_msg_buf);
return ret;
@@ -2291,7 +2318,7 @@ static int do_export_stash(struct repository *r,
.r = r, .items = iter,
};
if (refs_for_each_reflog_ent_reverse(get_main_ref_store(r),
- "refs/stash",
+ ref_stash,
collect_stash_entries,
&cb_data) && cb_data.count)
goto out;
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 0bb4648e36..d3af50e404 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -49,7 +49,7 @@ diff_cmp () {
rm -f "$1.compare" "$2.compare"
}
-setup_stash() {
+setup_stash () {
echo 1 >file &&
git add file &&
echo unrelated >other-file &&
@@ -60,13 +60,15 @@ setup_stash() {
git add file &&
echo 3 >file &&
test_tick &&
- git stash &&
+ git stash | tail -n 1 >actual &&
git diff-files --quiet &&
git diff-index --cached --quiet HEAD
}
-test_expect_success 'stash some dirty working directory' '
- setup_stash
+test_expect_success 'stash reports stash count' '
+ setup_stash &&
+ echo "Your stash now has 1 entry" >expect &&
+ test_cmp expect actual
'
cat >expect <<EOF
@@ -145,12 +147,14 @@ test_expect_success 'stash drop complains of extra options' '
test_expect_success 'drop top stash' '
git reset --hard &&
- git stash list >expected &&
+ git stash list >expect &&
echo 7 >file &&
git stash &&
- git stash drop &&
+ git stash drop | tail -n 1 >msg-actual &&
+ echo "Your stash now has 1 entry" >msg-expect &&
+ test_cmp msg-expect msg-actual &&
git stash list >actual &&
- test_cmp expected actual &&
+ test_cmp expect actual &&
git stash apply &&
test 3 = $(cat file) &&
test 1 = $(git show :file) &&
@@ -236,14 +240,18 @@ test_expect_success 'drop stash reflog updates refs/stash with rewrite' '
test_expect_success 'stash pop' '
git reset --hard &&
- git stash pop &&
+ git stash pop | tail -n 1 >actual &&
+ echo "Your stash now has 0 entries" >expect &&
+ test_cmp expect actual &&
test 3 = $(cat file) &&
test 1 = $(git show :file) &&
test 1 = $(git show HEAD:file) &&
test 0 = $(git stash list | wc -l)
'
-cat >expect <<EOF
+echo "Your stash now has 0 entries" >expect
+
+cat >expect1 <<EOF
diff --git a/file2 b/file2
new file mode 100644
index 0000000..1fe912c
@@ -253,7 +261,7 @@ index 0000000..1fe912c
+bar2
EOF
-cat >expect1 <<EOF
+cat >expect2 <<EOF
diff --git a/file b/file
index 257cc56..5716ca5 100644
--- a/file
@@ -263,7 +271,7 @@ index 257cc56..5716ca5 100644
+bar
EOF
-cat >expect2 <<EOF
+cat >expect3 <<EOF
diff --git a/file b/file
index 7601807..5716ca5 100644
--- a/file
@@ -289,17 +297,18 @@ test_expect_success 'stash branch' '
git stash &&
echo baz >file &&
git commit file -m second &&
- git stash branch stashbranch &&
+ git stash branch stashbranch | tail -n 1 >actual &&
+ test_cmp expect actual &&
test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
test $(git rev-parse HEAD) = $(git rev-parse main^) &&
git diff --cached >output &&
- diff_cmp expect output &&
- git diff >output &&
diff_cmp expect1 output &&
+ git diff >output &&
+ diff_cmp expect2 output &&
git add file &&
git commit -m alternate\ second &&
git diff main..stashbranch >output &&
- diff_cmp output expect2 &&
+ diff_cmp output expect3 &&
test 0 = $(git stash list | wc -l)
'
@@ -427,7 +436,9 @@ test_expect_success 'stash an added file' '
git reset --hard &&
echo new >file3 &&
git add file3 &&
- git stash save "added file" &&
+ git stash save "added file" | tail -n 1 >actual &&
+ echo "Your stash now has 6 entries" >expect &&
+ test_cmp expect actual &&
! test -r file3 &&
git stash apply &&
test new = "$(cat file3)"
@@ -683,12 +694,12 @@ test_expect_success 'stash show format defaults to --stat' '
echo bar >>file &&
STASH_ID=$(git stash create) &&
git reset --hard &&
- cat >expected <<-EOF &&
+ cat >expect <<-EOF &&
file | 1 +
1 file changed, 1 insertion(+)
EOF
git stash show ${STASH_ID} >actual &&
- test_cmp expected actual
+ test_cmp expect actual
'
test_expect_success 'stash show - stashes on stack, stash-like argument' '
@@ -701,9 +712,9 @@ test_expect_success 'stash show - stashes on stack, stash-like argument' '
echo bar >>file &&
STASH_ID=$(git stash create) &&
git reset --hard &&
- echo "1 0 file" >expected &&
+ echo "1 0 file" >expect &&
git stash show --numstat ${STASH_ID} >actual &&
- test_cmp expected actual
+ test_cmp expect actual
'
test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
@@ -716,7 +727,7 @@ test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
echo bar >>file &&
STASH_ID=$(git stash create) &&
git reset --hard &&
- cat >expected <<-EOF &&
+ cat >expect <<-EOF &&
diff --git a/file b/file
index 7601807..935fbd3 100644
--- a/file
@@ -726,7 +737,7 @@ test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
+bar
EOF
git stash show -p ${STASH_ID} >actual &&
- diff_cmp expected actual
+ diff_cmp expect actual
'
test_expect_success 'stash show - no stashes on stack, stash-like argument' '
@@ -736,9 +747,9 @@ test_expect_success 'stash show - no stashes on stack, stash-like argument' '
echo foo >>file &&
STASH_ID=$(git stash create) &&
git reset --hard &&
- echo "1 0 file" >expected &&
+ echo "1 0 file" >expect &&
git stash show --numstat ${STASH_ID} >actual &&
- test_cmp expected actual
+ test_cmp expect actual
'
test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
@@ -748,7 +759,7 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
echo foo >>file &&
STASH_ID=$(git stash create) &&
git reset --hard &&
- cat >expected <<-EOF &&
+ cat >expect <<-EOF &&
diff --git a/file b/file
index 7601807..71b52c4 100644
--- a/file
@@ -758,7 +769,7 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
+foo
EOF
git stash show -p ${STASH_ID} >actual &&
- diff_cmp expected actual
+ diff_cmp expect actual
'
test_expect_success 'stash show --patience shows diff' '
@@ -766,7 +777,7 @@ test_expect_success 'stash show --patience shows diff' '
echo foo >>file &&
STASH_ID=$(git stash create) &&
git reset --hard &&
- cat >expected <<-EOF &&
+ cat >expect <<-EOF &&
diff --git a/file b/file
index 7601807..71b52c4 100644
--- a/file
@@ -776,7 +787,7 @@ test_expect_success 'stash show --patience shows diff' '
+foo
EOF
git stash show --patience ${STASH_ID} >actual &&
- diff_cmp expected actual
+ diff_cmp expect actual
'
test_expect_success 'drop: fail early if specified stash is not a stash ref' '
@@ -915,7 +926,7 @@ test_expect_success 'apply: show same status as git status (relative to ./)' '
sane_unset GIT_MERGE_VERBOSITY &&
git stash apply
) |
- sed -e 1d >actual && # drop "Saved..."
+ sed -e 1,2d >actual && # drop "Your stash now has 1 entry" and "Saved..."
test_cmp expect actual
'
@@ -959,9 +970,11 @@ test_expect_success 'store updates stash ref and reflog' '
STASH_ID=$(git stash create) &&
git reset --hard &&
test_path_is_missing bazzy &&
- git stash store -m quuxery $STASH_ID &&
+ git stash store -m quuxery $STASH_ID | tail -n 1 >actual &&
+ echo "Your stash now has 1 entry" >expect &&
+ test_cmp expect actual &&
test $(git rev-parse stash) = $STASH_ID &&
- git reflog --format=%H stash| grep $STASH_ID &&
+ git reflog --format=%H stash | grep $STASH_ID &&
git stash pop &&
grep quux bazzy
'
diff --git a/wt-status.c b/wt-status.c
index 454601afa1..6bdf71efee 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -983,7 +983,7 @@ static int stash_count_refs(struct object_id *ooid UNUSED,
return 0;
}
-static int count_stash_entries(void)
+int count_stash_entries(void)
{
int n = 0;
refs_for_each_reflog_ent(get_main_ref_store(the_repository),
diff --git a/wt-status.h b/wt-status.h
index 4e377ce62b..daccde0b6e 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -151,6 +151,7 @@ size_t wt_status_locate_end(const char *s, size_t len);
void wt_status_append_cut_line(struct strbuf *buf);
void wt_status_add_cut_line(struct wt_status *s);
void wt_status_prepare(struct repository *r, struct wt_status *s);
+int count_stash_entries(void);
void wt_status_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);
/*
base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
--
gitgitgadget
next prev parent reply other threads:[~2025-10-09 11:03 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-06 11:35 [PATCH] stash: don't show irrelevant entry count in status Miroma via GitGitGadget
2025-10-06 14:43 ` Karthik Nayak
2025-10-06 17:21 ` Junio C Hamano
2025-10-06 18:24 ` Miroma
2025-10-09 11:03 ` Miroma via GitGitGadget [this message]
2025-10-12 16:45 ` [PATCH v2] stash: show correct entries count Miroma
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.2067.v2.git.git.1760007783388.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=its.miroma@proton.me \
--cc=karthik.188@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).