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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.