threads / patch / 66507

patch, 5 partsstash completion miscellany

Subject: [PATCH 0/5] stash completion miscellany

## tl;dr

D. Ben Knoble's five patches fix Zsh stash completion and drop "save" from completion and the usage synopsis, which Kristoffer Haugsbakk would rather keep. Read the story.

replies: 27people: 4as markdown or json

D. Ben Knoble· Oct 12, 2026, 17:48 UTC · lore
Hi all,

This short patch series takes care of a few paper cuts in stash completion. The first patch is a small code cleanup I noticed a while back while working on bfc1b34859 (completion: add stash import, export, 2026-02-07), I think. The next 2 take care of a problem I've been having with Zsh's completion of stashes (cf. Unix & Linux SE [1]).

[1]: https://unix.stackexchange.com/q/807580/301073

The final 2 are not only about completion; I noticed we were special-casing save completion, did some digging, and was a bit confused by the status of "git stash save". So, I figured while I was here I would start a conversation about (a) restoring the git-stash(1) manual to it's "no save" version and (b) ripping out the special case.

These last 2 may be controversial, and I'm not particularly attached to them, so if they need to be dropped I won't really complain. OTOH, what's the point of a deprecated subcommand we still advertise? ;)

Generated-with: git format-patch @{u}.. -o p

[1/5] completion: simplify stash subcommand completion [2/5] completion: extract common stash listing code [3/5] completion: fix Zsh handling of stash names [4/5] doc: drop usage mentions of "git stash save" [5/5] completion: drop "stash save" completion altogether

 Documentation/git-stash.adoc           |  2 --
 builtin/stash.c                        |  1 -
 contrib/completion/git-completion.bash | 22 +++++++++++++---------
 contrib/completion/git-completion.zsh  |  5 +++++
 4 files changed, 18 insertions(+), 12 deletions(-)
base-commit: 6de20f6092dcf9bdb1c8efe03db4b70c82b423dd
-- 
2.56.0.184.g5a00b4a6e9.dirty
D. Ben Knoble· Oct 12, 2026, 17:48 UTC · re: D. Ben Knoble · lore

[PATCH 1/5] completion: simplify stash subcommand completion

The stash completion helper contains a hard-coded list of commands, but git-stash provides a mechanism to list such commands (--git-completion-helper). The pattern for using it is wrapped by __git_resolve_builtins, so use it, bring _git_stash closer in line with other completion helpers.

Note that we maintain the "save" special case, since it was removed from default completion in 0eb5a4f911 (completion: stop showing 'save' for stash by default, 2018-04-20). We don't have to do anything special with the exclude (3rd) argument to __git_resolve_builtins, though, because save is already marked PARSE_OPT_NOCOMPLETE.

Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.bash | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
Show changes to contrib/completion/git-completion.bash +6 −2
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index c3a49e2e22..d60e85479c 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3553,8 +3553,12 @@ _git_sparse_checkout ()
 
 _git_stash ()
 {
-	local subcommands='push list show apply clear drop pop create branch import export'
-	local subcommand="$(__git_find_on_cmdline "$subcommands save")"
+	local subcommands subcommand
+
+	__git_resolve_builtins stash
+
+	subcommands="$___git_resolved_builtins"
+	subcommand="$(__git_find_on_cmdline "$subcommands save")"
 
 	if [ -z "$subcommand" ]; then
 		case "$((cword - __git_cmd_idx)),$cur" in
-- 
2.56.0.184.g5a00b4a6e9.dirty
Patrick Steinhardt· Oct 16, 2026, 08:01 UTC · re: D. Ben Knoble · lore

Re: [PATCH 1/5] completion: simplify stash subcommand completion

On Mon, Oct 12, 2026 at 01:48:27PM -0400, D. Ben Knoble wrote:
> The stash completion helper contains a hard-coded list of commands, but
> git-stash provides a mechanism to list such commands
> (--git-completion-helper). The pattern for using it is wrapped by
> __git_resolve_builtins, so use it, bring _git_stash closer in line with
s/bring/bringing/?
Show 7 quoted lines
> other completion helpers.
> 
> Note that we maintain the "save" special case, since it was removed from
> default completion in 0eb5a4f911 (completion: stop showing 'save' for
> stash by default, 2018-04-20). We don't have to do anything special with
> the exclude (3rd) argument to __git_resolve_builtins, though, because
> save is already marked PARSE_OPT_NOCOMPLETE.
I didn't understand the last sentence without going into the code.

I assume what you want to say is that we don't have to explicitly exclude it when completing the subcommand because it's already marked as NOCOMPLETE. But we don't want to fully ignore it, either, because we want to be able to complete that subcommand if the user explicitly wrote it?

So basically: we're not completing it if the user writes "git stash sa<TAB>", but we then know to complete its options if the user writes "git stash save --<TAB>". Which I guess makes sense for a deprecated subcommand.

Show 16 quoted lines
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index c3a49e2e22..d60e85479c 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -3553,8 +3553,12 @@ _git_sparse_checkout ()
>  
>  _git_stash ()
>  {
> -	local subcommands='push list show apply clear drop pop create branch import export'
> -	local subcommand="$(__git_find_on_cmdline "$subcommands save")"
> +	local subcommands subcommand
> +
> +	__git_resolve_builtins stash
> +
> +	subcommands="$___git_resolved_builtins"
> +	subcommand="$(__git_find_on_cmdline "$subcommands save")"

More plumbing, but less stuff that we need to keep up-to-date. This also fixes that the "store" subcommand wasn't completed, which should probably be pointed out in the commit message.

Patrick
Ben Knoble· Oct 19, 2026, 19:58 UTC · re: Patrick Steinhardt · lore

Re: [PATCH 1/5] completion: simplify stash subcommand completion

Show 9 quoted lines
> Le 16 oct. 2026 à 04:01, Patrick Steinhardt <ps@pks.im> a écrit :
> 
> On Mon, Oct 12, 2026 at 01:48:27PM -0400, D. Ben Knoble wrote:
>> The stash completion helper contains a hard-coded list of commands, but
>> git-stash provides a mechanism to list such commands
>> (--git-completion-helper). The pattern for using it is wrapped by
>> __git_resolve_builtins, so use it, bring _git_stash closer in line with
> 
> s/bring/bringing/?
Will fix!
Show 20 quoted lines
>> other completion helpers.
>> 
>> Note that we maintain the "save" special case, since it was removed from
>> default completion in 0eb5a4f911 (completion: stop showing 'save' for
>> stash by default, 2018-04-20). We don't have to do anything special with
>> the exclude (3rd) argument to __git_resolve_builtins, though, because
>> save is already marked PARSE_OPT_NOCOMPLETE.
> 
> I didn't understand the last sentence without going into the code.
> 
> I assume what you want to say is that we don't have to explicitly
> exclude it when completing the subcommand because it's already marked as
> NOCOMPLETE. But we don't want to fully ignore it, either, because we
> want to be able to complete that subcommand if the user explicitly wrote
> it?
> 
> So basically: we're not completing it if the user writes "git stash
> sa<TAB>", but we then know to complete its options if the user writes
> "git stash save --<TAB>". Which I guess makes sense for a deprecated
> subcommand.

Correct. I got a little too familiar with the completion guts while working on this. I’ll try reworking it when I get back to v2.

Show 18 quoted lines
>> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
>> index c3a49e2e22..d60e85479c 100644
>> --- a/contrib/completion/git-completion.bash
>> +++ b/contrib/completion/git-completion.bash
>> @@ -3553,8 +3553,12 @@ _git_sparse_checkout ()
>> 
>> _git_stash ()
>> {
>> -    local subcommands='push list show apply clear drop pop create branch import export'
>> -    local subcommand="$(__git_find_on_cmdline "$subcommands save")"
>> +    local subcommands subcommand
>> +
>> +    __git_resolve_builtins stash
>> +
>> +    subcommands="$___git_resolved_builtins"
>> +    subcommand="$(__git_find_on_cmdline "$subcommands save")"
> 
> More plumbing, but less stuff that we need to keep up-to-date.
And more aligned with other helpers, yep.
> This also
> fixes that the "store" subcommand wasn't completed, which should
> probably be pointed out in the commit message.
I missed that, will add. Thanks!
D. Ben Knoble· Oct 12, 2026, 17:48 UTC · re: D. Ben Knoble · lore

[PATCH 2/5] completion: extract common stash listing code

With no change in behavior, prepare to adjust how stashes are completed by centralizing candidate generation.

Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.bash | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
Show changes to contrib/completion/git-completion.bash +7 −4
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d60e85479c..697fef5462 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3593,20 +3593,23 @@ _git_stash ()
 		if [ $cword -eq $((__git_cmd_idx+2)) ]; then
 			__git_complete_refs
 		else
-			__gitcomp_nl "$(__git stash list \
-					| sed -n -e 's/:.*//p')"
+			__git_complete_stashes
 		fi
 		;;
 	import,*)
 		__git_complete_refs
 		;;
 	show,*|apply,*|drop,*|pop,*|export,*)
-		__gitcomp_nl "$(__git stash list \
-				| sed -n -e 's/:.*//p')"
+		__git_complete_stashes
 		;;
 	esac
 }
 
+__git_complete_stashes ()
+{
+	__gitcomp_nl "$(__git stash list | sed -n -e 's/:.*//p')"
+}
+
 _git_submodule ()
 {
 	__git_has_doubledash && return
-- 
2.56.0.184.g5a00b4a6e9.dirty
D. Ben Knoble· Oct 12, 2026, 17:48 UTC · re: D. Ben Knoble · lore

[PATCH 3/5] completion: fix Zsh handling of stash names

When Git completes stashes for Zsh, it eventually invokes something like this (via our redefinition of __gitcomp_nl):

    compadd -Q -S " " -p "" -- 'stash@{0}' 'stash@{1}' && _ret=0

Because of -Q, the braces are unquoted, and Zsh will leave us at (for example)

    git stash show stash@{
                   cursor ^

From here, the list-choices widget (on Ctrl-D by default) will show stash@{0} and stash@{1}, but the complete-word widget (Tab) will just add another brace. Zsh things we're trying to do a brace expansion, I think! Interestingly, using menu-complete (Ctrl-N) does cycle through matches, since it's taking a slightly different completion path in Zsh.

We might try to fix this by passing surrounding single quotes (using the -S/-p arguments of compadd, which we can do via __gitcomp_nl's other parameters), and indeed Zsh will generate

    git stash show 'stash@{
                    cursor ^
but completing here won't find anything, and I'm not totally sure why.

Instead, though, we can let Zsh quote metacharacters (removing -Q) and everything "just works." It changes the output format a bit (users see stash@\{0\}, for example), but I find this an improvement over not being able to complete names at all. menu-complete is unchanged aside from the extra backslashes.

So, override stash listing completion in Zsh with a working version.
Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.zsh | 5 +++++
 1 file changed, 5 insertions(+)
Show changes to contrib/completion/git-completion.zsh +5 −0
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index d5c526665b..2aea7770d2 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -135,6 +135,11 @@ __gitcomp_file_direct ()
 	__gitcomp_file "$1" ""
 }
 
+__git_complete_stashes ()
+{
+	compadd -S ' ' -- ${(f)"$(__git stash list | sed -n -e 's/:.*//p')"} && _ret=0
+}
+
 _git_zsh ()
 {
 	__gitcomp "v1.1"
-- 
2.56.0.184.g5a00b4a6e9.dirty
Patrick Steinhardt· Oct 16, 2026, 08:01 UTC · re: D. Ben Knoble · lore

Re: [PATCH 3/5] completion: fix Zsh handling of stash names

On Mon, Oct 12, 2026 at 01:48:29PM -0400, D. Ben Knoble wrote:
Show 14 quoted lines
> When Git completes stashes for Zsh, it eventually invokes something like
> this (via our redefinition of __gitcomp_nl):
> 
>     compadd -Q -S " " -p "" -- 'stash@{0}' 'stash@{1}' && _ret=0
> 
> Because of -Q, the braces are unquoted, and Zsh will leave us at (for
> example)
> 
>     git stash show stash@{
>                    cursor ^
> 
> From here, the list-choices widget (on Ctrl-D by default) will show
> stash@{0} and stash@{1}, but the complete-word widget (Tab) will just
> add another brace. Zsh things we're trying to do a brace expansion, I
s/things/thinks/
Show 19 quoted lines
> think! Interestingly, using menu-complete (Ctrl-N) does cycle through
> matches, since it's taking a slightly different completion path in Zsh.
> 
> We might try to fix this by passing surrounding single quotes (using the
> -S/-p arguments of compadd, which we can do via __gitcomp_nl's other
> parameters), and indeed Zsh will generate
> 
>     git stash show 'stash@{
>                     cursor ^
> 
> but completing here won't find anything, and I'm not totally sure why.
> 
> Instead, though, we can let Zsh quote metacharacters (removing -Q) and
> everything "just works." It changes the output format a bit (users see
> stash@\{0\}, for example), but I find this an improvement over not being
> able to complete names at all. menu-complete is unchanged aside from the
> extra backslashes.
> 
> So, override stash listing completion in Zsh with a working version.

Hm. I assume you tried finding a variant that works for both Bash and Zsh so that we don't have to carry this override?

Show 12 quoted lines
> diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
> index d5c526665b..2aea7770d2 100644
> --- a/contrib/completion/git-completion.zsh
> +++ b/contrib/completion/git-completion.zsh
> @@ -135,6 +135,11 @@ __gitcomp_file_direct ()
>  	__gitcomp_file "$1" ""
>  }
>  
> +__git_complete_stashes ()
> +{
> +	compadd -S ' ' -- ${(f)"$(__git stash list | sed -n -e 's/:.*//p')"} && _ret=0
> +}
Patrick
Ben Knoble· Oct 19, 2026, 19:56 UTC · re: Patrick Steinhardt · lore

Re: [PATCH 3/5] completion: fix Zsh handling of stash names

Show 19 quoted lines
> Le 16 oct. 2026 à 04:01, Patrick Steinhardt <ps@pks.im> a écrit :
> 
> On Mon, Oct 12, 2026 at 01:48:29PM -0400, D. Ben Knoble wrote:
>> When Git completes stashes for Zsh, it eventually invokes something like
>> this (via our redefinition of __gitcomp_nl):
>> 
>>    compadd -Q -S " " -p "" -- 'stash@{0}' 'stash@{1}' && _ret=0
>> 
>> Because of -Q, the braces are unquoted, and Zsh will leave us at (for
>> example)
>> 
>>    git stash show stash@{
>>                   cursor ^
>> 
>> From here, the list-choices widget (on Ctrl-D by default) will show
>> stash@{0} and stash@{1}, but the complete-word widget (Tab) will just
>> add another brace. Zsh things we're trying to do a brace expansion, I
> 
> s/things/thinks/
Will fix!
Show 22 quoted lines
>> think! Interestingly, using menu-complete (Ctrl-N) does cycle through
>> matches, since it's taking a slightly different completion path in Zsh.
>> 
>> We might try to fix this by passing surrounding single quotes (using the
>> -S/-p arguments of compadd, which we can do via __gitcomp_nl's other
>> parameters), and indeed Zsh will generate
>> 
>>    git stash show 'stash@{
>>                    cursor ^
>> 
>> but completing here won't find anything, and I'm not totally sure why.
>> 
>> Instead, though, we can let Zsh quote metacharacters (removing -Q) and
>> everything "just works." It changes the output format a bit (users see
>> stash@\{0\}, for example), but I find this an improvement over not being
>> able to complete names at all. menu-complete is unchanged aside from the
>> extra backslashes.
>> 
>> So, override stash listing completion in Zsh with a working version.
> 
> Hm. I assume you tried finding a variant that works for both Bash and
> Zsh so that we don't have to carry this override?

Actually, no. I assumed Bash was working and haven’t tested it either way. Presumably we’d have a report from someone if it were doing what Zsh does?

Many Zsh users, OTOH, use the Zsh-distributed completions, which stackoverflow for me (and anyway I prefer ours).

I won’t have time to see if Bash is also Brien here, but this shouldn’t change Bash’s behavior at least.

Oh, re-reading: yes, I looked for something that was compatible with existing code. I mentioned one such attempt (single quotes). No luck, though.

D. Ben Knoble· Oct 12, 2026, 17:48 UTC · re: D. Ben Knoble · lore

[PATCH 4/5] doc: drop usage mentions of "git stash save"

Even though we previously deprecated it in fd2ebf14db (stash: mark "git stash save" deprecated in the man page, 2017-10-22), the save subcommand clings to life. For example, 951ec747d4 (doc txt & -h consistency: make "stash" consistent, 2022-10-13) brought back "save" to the git-stash(1) synopsis, and 41a28eb6c1 (stash: implement '--staged' option for 'push' and 'save', 2021-10-18) gave it new options. But we really discourage its use in modern Git, so let's drop mention of it from -h usage and the synopsis.

It's still described in the manual, since some descriptions talk about the "save" command. As we haven't gone ahead with a full deprecation and removal, we can leave these pieces for folks whose fingers still type "save" and need a reference for its behavior.

Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
Notes (benknoble/commits):
    AFAICT there was no discussion of its deprecation when re-adding save to
    the documentation, so I wonder if that was just an oversight.
 Documentation/git-stash.adoc | 2 --
 builtin/stash.c              | 1 -
 2 files changed, 3 deletions(-)
Show changes to 2 files +0 −3

Documentation/git-stash.adoc, builtin/stash.c

diff --git a/Documentation/git-stash.adoc b/Documentation/git-stash.adoc
index d6e8c4144c..6bf510702b 100644
--- a/Documentation/git-stash.adoc
+++ b/Documentation/git-stash.adoc
@@ -18,8 +18,6 @@ git stash [push] [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | -
 	     [-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
 	     [--pathspec-from-file=<file> [--pathspec-file-nul]]
 	     [--] [<pathspec>...]
-git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
-           [-u | --include-untracked] [-a | --all] [<message>]
 git stash clear
 git stash create [<message>]
 git stash store [(-m | --message) <message>] [-q | --quiet] <commit>
diff --git a/builtin/stash.c b/builtin/stash.c
index 7a9843413b..94869c2429 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -75,7 +75,6 @@ static const char * const git_stash_usage[] = {
 	BUILTIN_STASH_APPLY_USAGE,
 	BUILTIN_STASH_BRANCH_USAGE,
 	BUILTIN_STASH_PUSH_USAGE,
-	BUILTIN_STASH_SAVE_USAGE,
 	BUILTIN_STASH_CLEAR_USAGE,
 	BUILTIN_STASH_CREATE_USAGE,
 	BUILTIN_STASH_STORE_USAGE,
-- 
2.56.0.184.g5a00b4a6e9.dirty
Patrick Steinhardt· Oct 16, 2026, 08:01 UTC · re: D. Ben Knoble · lore

Re: [PATCH 4/5] doc: drop usage mentions of "git stash save"

On Mon, Oct 12, 2026 at 01:48:30PM -0400, D. Ben Knoble wrote:
> Even though we previously deprecated it in fd2ebf14db (stash: mark "git
> stash save" deprecated in the man page, 2017-10-22), the save subcommand
> clings to life. For example, 951ec747d4 (doc txt & -h consistency: make
Heh :)
Show 10 quoted lines
> "stash" consistent, 2022-10-13) brought back "save" to the git-stash(1)
> synopsis, and 41a28eb6c1 (stash: implement '--staged' option for 'push'
> and 'save', 2021-10-18) gave it new options. But we really discourage
> its use in modern Git, so let's drop mention of it from -h usage and the
> synopsis.
> 
> It's still described in the manual, since some descriptions talk about
> the "save" command. As we haven't gone ahead with a full deprecation and
> removal, we can leave these pieces for folks whose fingers still type
> "save" and need a reference for its behavior.

I was wondering why we still have the command as part of our synopsis in case it's deprecated, so good that you address this, too.

Show 6 quoted lines
> Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
> ---
> 
> Notes (benknoble/commits):
>     AFAICT there was no discussion of its deprecation when re-adding save to
>     the documentation, so I wonder if that was just an oversight.
I bet. In any case, I agree with removing it from our synopsis again.
Patrick
D. Ben Knoble· Oct 12, 2026, 17:48 UTC · re: D. Ben Knoble · lore

[PATCH 5/5] completion: drop "stash save" completion altogether

It's been deprecated since fd2ebf14db (stash: mark "git stash save" deprecated in the man page, 2017-10-22) and the previous commit removed further documentation suggesting to use it.

Since we recommend push instead, stop completing for "save" and remove a special case in completion code.

Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.bash | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)
Show changes to contrib/completion/git-completion.bash +1 −4
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 697fef5462..9cd9c7cadb 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3558,16 +3558,13 @@ _git_stash ()
 	__git_resolve_builtins stash
 
 	subcommands="$___git_resolved_builtins"
-	subcommand="$(__git_find_on_cmdline "$subcommands save")"
+	subcommand="$(__git_find_on_cmdline "$subcommands")"
 
 	if [ -z "$subcommand" ]; then
 		case "$((cword - __git_cmd_idx)),$cur" in
 		*,--*)
 			__gitcomp_builtin stash_push
 			;;
-		1,sa*)
-			__gitcomp "save"
-			;;
 		1,*)
 			__gitcomp "$subcommands"
 			;;
-- 
2.56.0.184.g5a00b4a6e9.dirty
Patrick Steinhardt· Oct 16, 2026, 08:01 UTC · re: D. Ben Knoble · lore

Re: [PATCH 5/5] completion: drop "stash save" completion altogether

On Mon, Oct 12, 2026 at 01:48:31PM -0400, D. Ben Knoble wrote:
Show 6 quoted lines
> It's been deprecated since fd2ebf14db (stash: mark "git stash save"
> deprecated in the man page, 2017-10-22) and the previous commit removed
> further documentation suggesting to use it.
> 
> Since we recommend push instead, stop completing for "save" and remove a
> special case in completion code.

This is the only part I'm a bit torn on. I think it's reasonable to not autocomplete the "save" command, but if the user manually types it, should we really stop autocompleting its options altogether?

Maybe the answer is "yes". After all, as you mentioned in the preceding commit, the command is deprecated since 2017 already! And after almost 10 years I think it's fair to start giving users more nudges into the direction of using "push" instead.

One note though: the command _will_ be completed in the case where you have GIT_COMPLETION_SHOW_ALL set.

Patrick
Ben Knoble· Oct 19, 2026, 20:01 UTC · re: Patrick Steinhardt · lore

Re: [PATCH 5/5] completion: drop "stash save" completion altogether

Show 21 quoted lines
> Le 16 oct. 2026 à 04:01, Patrick Steinhardt <ps@pks.im> a écrit :
> 
> On Mon, Oct 12, 2026 at 01:48:31PM -0400, D. Ben Knoble wrote:
>> It's been deprecated since fd2ebf14db (stash: mark "git stash save"
>> deprecated in the man page, 2017-10-22) and the previous commit removed
>> further documentation suggesting to use it.
>> 
>> Since we recommend push instead, stop completing for "save" and remove a
>> special case in completion code.
> 
> This is the only part I'm a bit torn on. I think it's reasonable to not
> autocomplete the "save" command, but if the user manually types it,
> should we really stop autocompleting its options altogether?
> 
> Maybe the answer is "yes". After all, as you mentioned in the preceding
> commit, the command is deprecated since 2017 already! And after almost
> 10 years I think it's fair to start giving users more nudges into the
> direction of using "push" instead.
> 
> One note though: the command _will_ be completed in the case where you
> have GIT_COMPLETION_SHOW_ALL set

I should definitely mention SHOW_ALL; I’m not actually sure what happens for « git stash save --<TAB> » with this patch, so I’ll double-check. I actually wonder if it will complete options.

Would that satisfy you if so ?
Patrick Steinhardt· Oct 20, 2026, 06:05 UTC · re: Ben Knoble · lore

Re: [PATCH 5/5] completion: drop "stash save" completion altogether

On Mon, Oct 19, 2026 at 04:01:15PM -0400, Ben Knoble wrote:
Show 28 quoted lines
> 
> > Le 16 oct. 2026 à 04:01, Patrick Steinhardt <ps@pks.im> a écrit :
> > 
> > On Mon, Oct 12, 2026 at 01:48:31PM -0400, D. Ben Knoble wrote:
> >> It's been deprecated since fd2ebf14db (stash: mark "git stash save"
> >> deprecated in the man page, 2017-10-22) and the previous commit removed
> >> further documentation suggesting to use it.
> >> 
> >> Since we recommend push instead, stop completing for "save" and remove a
> >> special case in completion code.
> > 
> > This is the only part I'm a bit torn on. I think it's reasonable to not
> > autocomplete the "save" command, but if the user manually types it,
> > should we really stop autocompleting its options altogether?
> > 
> > Maybe the answer is "yes". After all, as you mentioned in the preceding
> > commit, the command is deprecated since 2017 already! And after almost
> > 10 years I think it's fair to start giving users more nudges into the
> > direction of using "push" instead.
> > 
> > One note though: the command _will_ be completed in the case where you
> > have GIT_COMPLETION_SHOW_ALL set
> 
> I should definitely mention SHOW_ALL; I’m not actually sure 
> what happens for « git stash save --<TAB> » with this patch,
> so I’ll double-check. I actually wonder if it will complete options.
> 
> Would that satisfy you if so ?

Probably depends on the outcome of your tests, but ultimately I think I'd be fine with either of the options. But if we stop autocompleting we should definitely mention SHOW_ALL.

Thanks!
Patrick
D. Ben Knoble· Oct 22, 2026, 13:14 UTC · re: Patrick Steinhardt · lore

Re: [PATCH 5/5] completion: drop "stash save" completion altogether

On Tue, Oct 20, 2026 at 2:05 AM Patrick Steinhardt <ps@pks.im> wrote:
Show 34 quoted lines
>
> On Mon, Oct 19, 2026 at 04:01:15PM -0400, Ben Knoble wrote:
> >
> > > Le 16 oct. 2026 à 04:01, Patrick Steinhardt <ps@pks.im> a écrit :
> > >
> > > On Mon, Oct 12, 2026 at 01:48:31PM -0400, D. Ben Knoble wrote:
> > >> It's been deprecated since fd2ebf14db (stash: mark "git stash save"
> > >> deprecated in the man page, 2017-10-22) and the previous commit removed
> > >> further documentation suggesting to use it.
> > >>
> > >> Since we recommend push instead, stop completing for "save" and remove a
> > >> special case in completion code.
> > >
> > > This is the only part I'm a bit torn on. I think it's reasonable to not
> > > autocomplete the "save" command, but if the user manually types it,
> > > should we really stop autocompleting its options altogether?
> > >
> > > Maybe the answer is "yes". After all, as you mentioned in the preceding
> > > commit, the command is deprecated since 2017 already! And after almost
> > > 10 years I think it's fair to start giving users more nudges into the
> > > direction of using "push" instead.
> > >
> > > One note though: the command _will_ be completed in the case where you
> > > have GIT_COMPLETION_SHOW_ALL set
> >
> > I should definitely mention SHOW_ALL; I’m not actually sure
> > what happens for « git stash save --<TAB> » with this patch,
> > so I’ll double-check. I actually wonder if it will complete options.
> >
> > Would that satisfy you if so ?
>
> Probably depends on the outcome of your tests, but ultimately I think
> I'd be fine with either of the options. But if we stop autocompleting we
> should definitely mention SHOW_ALL.
Here's what my testing showed (all Zsh):
- with SHOW_ALL, "git stash <tab>" lists "save" as an option; "git
stash save --<tab>" completes options
- without SHOW_ALL, "git stash <tab>" does not list "save"; "git stash
sa<tab>" does not complete "save"; "git stash save --<tab>" completes
options
I'll update the commit locally to reflect this. Thoughts?
-- 
D. Ben Knoble
Patrick Steinhardt· Oct 23, 2026, 06:21 UTC · re: D. Ben Knoble · lore

Re: [PATCH 5/5] completion: drop "stash save" completion altogether

On Thu, Oct 22, 2026 at 09:14:52AM -0400, D. Ben Knoble wrote:
Show 45 quoted lines
> On Tue, Oct 20, 2026 at 2:05 AM Patrick Steinhardt <ps@pks.im> wrote:
> >
> > On Mon, Oct 19, 2026 at 04:01:15PM -0400, Ben Knoble wrote:
> > >
> > > > Le 16 oct. 2026 à 04:01, Patrick Steinhardt <ps@pks.im> a écrit :
> > > >
> > > > On Mon, Oct 12, 2026 at 01:48:31PM -0400, D. Ben Knoble wrote:
> > > >> It's been deprecated since fd2ebf14db (stash: mark "git stash save"
> > > >> deprecated in the man page, 2017-10-22) and the previous commit removed
> > > >> further documentation suggesting to use it.
> > > >>
> > > >> Since we recommend push instead, stop completing for "save" and remove a
> > > >> special case in completion code.
> > > >
> > > > This is the only part I'm a bit torn on. I think it's reasonable to not
> > > > autocomplete the "save" command, but if the user manually types it,
> > > > should we really stop autocompleting its options altogether?
> > > >
> > > > Maybe the answer is "yes". After all, as you mentioned in the preceding
> > > > commit, the command is deprecated since 2017 already! And after almost
> > > > 10 years I think it's fair to start giving users more nudges into the
> > > > direction of using "push" instead.
> > > >
> > > > One note though: the command _will_ be completed in the case where you
> > > > have GIT_COMPLETION_SHOW_ALL set
> > >
> > > I should definitely mention SHOW_ALL; I’m not actually sure
> > > what happens for « git stash save --<TAB> » with this patch,
> > > so I’ll double-check. I actually wonder if it will complete options.
> > >
> > > Would that satisfy you if so ?
> >
> > Probably depends on the outcome of your tests, but ultimately I think
> > I'd be fine with either of the options. But if we stop autocompleting we
> > should definitely mention SHOW_ALL.
> 
> Here's what my testing showed (all Zsh):
> 
> - with SHOW_ALL, "git stash <tab>" lists "save" as an option; "git
> stash save --<tab>" completes options
> - without SHOW_ALL, "git stash <tab>" does not list "save"; "git stash
> sa<tab>" does not complete "save"; "git stash save --<tab>" completes
> options
> 
> I'll update the commit locally to reflect this. Thoughts?

We could of course add logic to explicitly stop completing options for the deprecated subcommand. But I doubt it's worth it? So I think this is good enough.

Patrick
D. Ben Knoble· Oct 23, 2026, 13:20 UTC · re: D. Ben Knoble · lore

[PATCH v2 0/5] stash completion miscellany

Hi all,

This short patch series takes care of a few paper cuts in stash completion. The first patch is a small code cleanup I noticed a while back while working on bfc1b34859 (completion: add stash import, export, 2026-02-07), I think. The next 2 take care of a problem I've been having with Zsh's completion of stashes (cf. Unix & Linux SE [1]).

[1]: https://unix.stackexchange.com/q/807580/301073
Changes in v2:
• Reworded a few commit messages thanks to Patrick
• Clarify the behavior of the final patches with completion for "git
  stash save" (also thanks to Patrick)

The final 2 are not only about completion; I noticed we were special-casing save completion, did some digging, and was a bit confused by the status of "git stash save". So, I figured while I was here I would start a conversation about (a) restoring the git-stash(1) manual to it's "no save" version and (b) ripping out the special case.

These last 2 may be controversial, and I'm not particularly attached to them, so if they need to be dropped I won't really complain. OTOH, what's the point of a deprecated subcommand we still advertise? ;)

Generated-with: git format-patch @{u}.. -o p -v2 --range-diff=@{u}..d1d0bf2d9a7d380d10771b5d1bceb8db91c5f05e --in-reply-to=cover.1791827304.git.ben.knoble@gmail.com --cc='Patrick Steinhardt <ps@pks.im>'

I accidentally left the above line in v1, but I'm considering leaving it in from now on? It's the exact command I run to generate patches; I store it as a "trailer" in the branch description, then run "git generated-with"† which (effectively) does

    eval "$(git bdesc | git interpret-trailers --parse | grep ^Generated-with | cut -d: -f 2-)"
where "bdesc" is an alias for
    git -c core.editor=cat branch --edit-description | git stripspace -s

Anyway, I've been hand-editing them out of cover letters for the last few series, but if it doesn't bother anyone I'll just leave it around. Might be helpful for new folks learning how to format patches?

†: https://github.com/benknoble/Dotfiles/blob/master/links/bin/git-generated-with

[1/5] completion: simplify stash subcommand completion [2/5] Completion: extract common stash listing code [3/5] completion: fix Zsh handling of stash names [4/5] doc: drop usage mentions of "git stash save" [5/5] completion: drop "stash save" completion altogether

 Documentation/git-stash.adoc           |  2 --
 builtin/stash.c                        |  1 -
 contrib/completion/git-completion.bash | 22 +++++++++++++---------
 contrib/completion/git-completion.zsh  |  5 +++++
 4 files changed, 18 insertions(+), 12 deletions(-)
Diff-intervalle contre v1 :
1:  d0e461a14a ! 1:  90d36b6445 completion: simplify stash subcommand completion
    @@ Commit message
         The stash completion helper contains a hard-coded list of commands, but
         git-stash provides a mechanism to list such commands
         (--git-completion-helper). The pattern for using it is wrapped by
    -    __git_resolve_builtins, so use it, bring _git_stash closer in line with
    -    other completion helpers.
    +    __git_resolve_builtins, so use it, bringing _git_stash closer in line
    +    with other completion helpers. As a nice side-benefit, this also adds
    +    "store" subcommand completion, which is missing from the explicit list
    +    of subcommands.
     
    -    Note that we maintain the "save" special case, since it was removed from
    +    Note that we maintain the "save" special case†, since it was removed from
         default completion in 0eb5a4f911 (completion: stop showing 'save' for
    -    stash by default, 2018-04-20). We don't have to do anything special with
    -    the exclude (3rd) argument to __git_resolve_builtins, though, because
    -    save is already marked PARSE_OPT_NOCOMPLETE.
    +    stash by default, 2018-04-20). One might think we need to give "save" to
    +    __git_resolve_builtins' 3rd exclude argument to prevent it from
    +    showing up, but we don't: "save" is already marked PARSE_OPT_NOCOMPLETE.
    +
    +    †We don't complete the "save" subcommand unless at least "sa" has been
    +    typed, but we do complete its options if explicitly typed. With this
    +    change, we will complete "save" if GIT_COMPLETION_SHOW_ALL=1.
     
      ## contrib/completion/git-completion.bash ##
     @@ contrib/completion/git-completion.bash: _git_sparse_checkout ()
2:  6c24a833fc = 2:  abf8efb792 Completion: extract common stash listing code
3:  22283a1d5f ! 3:  f4f6b89ff6 completion: fix Zsh handling of stash names
    @@ Commit message
     
         From here, the list-choices widget (on Ctrl-D by default) will show
         stash@{0} and stash@{1}, but the complete-word widget (Tab) will just
    -    add another brace. Zsh things we're trying to do a brace expansion, I
    +    add another brace. Zsh thinks we're trying to do a brace expansion, I
         think! Interestingly, using menu-complete (Ctrl-N) does cycle through
         matches, since it's taking a slightly different completion path in Zsh.
     
         We might try to fix this by passing surrounding single quotes (using the
    -    -S/-p arguments of compadd, which we can do via __gitcomp_nl's other
    -    parameters), and indeed Zsh will generate
    +    -S/-p arguments of compadd, which we can do from Bash in our code via
    +    __gitcomp_nl's other parameters), and indeed Zsh will generate
     
             git stash show 'stash@{
                             cursor ^
4:  985a14f18e = 4:  3762f9d5bb doc: drop usage mentions of "git stash save"
5:  d1d0bf2d9a ! 5:  0266646fb4 completion: drop "stash save" completion altogether
    @@ Commit message
         further documentation suggesting to use it.
     
         Since we recommend push instead, stop completing for "save" and remove a
    -    special case in completion code.
    +    special case in completion code. It still appears for "git stash <tab>"
    +    when GIT_COMPLETION_SHOW_ALL=1, and when typed explicitly we still
    +    complete options for
    +
    +        git stash save --<tab>
    +
    +    which is helpful for folks with finger-memory for save.
     
      ## contrib/completion/git-completion.bash ##
     @@ contrib/completion/git-completion.bash: _git_stash ()
base-commit: 6de20f6092dcf9bdb1c8efe03db4b70c82b423dd
-- 
2.56.0.237.g5414b88716.dirty
D. Ben Knoble· Oct 23, 2026, 13:20 UTC · re: D. Ben Knoble · lore

[PATCH v2 1/5] completion: simplify stash subcommand completion

The stash completion helper contains a hard-coded list of commands, but git-stash provides a mechanism to list such commands (--git-completion-helper). The pattern for using it is wrapped by __git_resolve_builtins, so use it, bringing _git_stash closer in line with other completion helpers. As a nice side-benefit, this also adds "store" subcommand completion, which is missing from the explicit list of subcommands.

Note that we maintain the "save" special case†, since it was removed from default completion in 0eb5a4f911 (completion: stop showing 'save' for stash by default, 2018-04-20). One might think we need to give "save" to __git_resolve_builtins' 3rd exclude argument to prevent it from showing up, but we don't: "save" is already marked PARSE_OPT_NOCOMPLETE.

†We don't complete the "save" subcommand unless at least "sa" has been typed, but we do complete its options if explicitly typed. With this change, we will complete "save" if GIT_COMPLETION_SHOW_ALL=1.

Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.bash | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
Show changes to contrib/completion/git-completion.bash +6 −2
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index c3a49e2e22..d60e85479c 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3553,8 +3553,12 @@ _git_sparse_checkout ()
 
 _git_stash ()
 {
-	local subcommands='push list show apply clear drop pop create branch import export'
-	local subcommand="$(__git_find_on_cmdline "$subcommands save")"
+	local subcommands subcommand
+
+	__git_resolve_builtins stash
+
+	subcommands="$___git_resolved_builtins"
+	subcommand="$(__git_find_on_cmdline "$subcommands save")"
 
 	if [ -z "$subcommand" ]; then
 		case "$((cword - __git_cmd_idx)),$cur" in
-- 
2.56.0.237.g5414b88716.dirty
D. Ben Knoble· Oct 23, 2026, 13:20 UTC · re: D. Ben Knoble · lore

[PATCH v2 2/5] Completion: extract common stash listing code

With no change in behavior, prepare to adjust how stashes are completed by centralizing candidate generation.

Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.bash | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
Show changes to contrib/completion/git-completion.bash +7 −4
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d60e85479c..697fef5462 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3593,20 +3593,23 @@ _git_stash ()
 		if [ $cword -eq $((__git_cmd_idx+2)) ]; then
 			__git_complete_refs
 		else
-			__gitcomp_nl "$(__git stash list \
-					| sed -n -e 's/:.*//p')"
+			__git_complete_stashes
 		fi
 		;;
 	import,*)
 		__git_complete_refs
 		;;
 	show,*|apply,*|drop,*|pop,*|export,*)
-		__gitcomp_nl "$(__git stash list \
-				| sed -n -e 's/:.*//p')"
+		__git_complete_stashes
 		;;
 	esac
 }
 
+__git_complete_stashes ()
+{
+	__gitcomp_nl "$(__git stash list | sed -n -e 's/:.*//p')"
+}
+
 _git_submodule ()
 {
 	__git_has_doubledash && return
-- 
2.56.0.237.g5414b88716.dirty
Junio C Hamano· Oct 23, 2026, 17:06 UTC · re: D. Ben Knoble · lore

Re: [PATCH v2 2/5] Completion: extract common stash listing code

"D. Ben Knoble" <ben.knoble@gmail.com> writes:
Show 18 quoted lines
> With no change in behavior, prepare to adjust how stashes are completed
> by centralizing candidate generation.
>
> Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
> ---
>  contrib/completion/git-completion.bash | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> @@ -3593,20 +3593,23 @@ _git_stash ()
>  		if [ $cword -eq $((__git_cmd_idx+2)) ]; then
>  			__git_complete_refs
>  		else
> -			__gitcomp_nl "$(__git stash list \
> -					| sed -n -e 's/:.*//p')"
> +			__git_complete_stashes
> ...
> -		__gitcomp_nl "$(__git stash list \
> -				| sed -n -e 's/:.*//p')"
> +		__git_complete_stashes
Nice to see two of these unsightly constructs go ;-)
D. Ben Knoble· Oct 23, 2026, 13:20 UTC · re: D. Ben Knoble · lore

[PATCH v2 3/5] completion: fix Zsh handling of stash names

When Git completes stashes for Zsh, it eventually invokes something like this (via our redefinition of __gitcomp_nl):

    compadd -Q -S " " -p "" -- 'stash@{0}' 'stash@{1}' && _ret=0

Because of -Q, the braces are unquoted, and Zsh will leave us at (for example)

    git stash show stash@{
                   cursor ^

From here, the list-choices widget (on Ctrl-D by default) will show stash@{0} and stash@{1}, but the complete-word widget (Tab) will just add another brace. Zsh thinks we're trying to do a brace expansion, I think! Interestingly, using menu-complete (Ctrl-N) does cycle through matches, since it's taking a slightly different completion path in Zsh.

We might try to fix this by passing surrounding single quotes (using the -S/-p arguments of compadd, which we can do from Bash in our code via __gitcomp_nl's other parameters), and indeed Zsh will generate

    git stash show 'stash@{
                    cursor ^
but completing here won't find anything, and I'm not totally sure why.

Instead, though, we can let Zsh quote metacharacters (removing -Q) and everything "just works." It changes the output format a bit (users see stash@\{0\}, for example), but I find this an improvement over not being able to complete names at all. menu-complete is unchanged aside from the extra backslashes.

So, override stash listing completion in Zsh with a working version.
Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.zsh | 5 +++++
 1 file changed, 5 insertions(+)
Show changes to contrib/completion/git-completion.zsh +5 −0
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index d5c526665b..2aea7770d2 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -135,6 +135,11 @@ __gitcomp_file_direct ()
 	__gitcomp_file "$1" ""
 }
 
+__git_complete_stashes ()
+{
+	compadd -S ' ' -- ${(f)"$(__git stash list | sed -n -e 's/:.*//p')"} && _ret=0
+}
+
 _git_zsh ()
 {
 	__gitcomp "v1.1"
-- 
2.56.0.237.g5414b88716.dirty
D. Ben Knoble· Oct 23, 2026, 13:20 UTC · re: D. Ben Knoble · lore

[PATCH v2 4/5] doc: drop usage mentions of "git stash save"

Even though we previously deprecated it in fd2ebf14db (stash: mark "git stash save" deprecated in the man page, 2017-10-22), the save subcommand clings to life. For example, 951ec747d4 (doc txt & -h consistency: make "stash" consistent, 2022-10-13) brought back "save" to the git-stash(1) synopsis, and 41a28eb6c1 (stash: implement '--staged' option for 'push' and 'save', 2021-10-18) gave it new options. But we really discourage its use in modern Git, so let's drop mention of it from -h usage and the synopsis.

It's still described in the manual, since some descriptions talk about the "save" command. As we haven't gone ahead with a full deprecation and removal, we can leave these pieces for folks whose fingers still type "save" and need a reference for its behavior.

Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 Documentation/git-stash.adoc | 2 --
 builtin/stash.c              | 1 -
 2 files changed, 3 deletions(-)
Show changes to 2 files +0 −3

Documentation/git-stash.adoc, builtin/stash.c

diff --git a/Documentation/git-stash.adoc b/Documentation/git-stash.adoc
index d6e8c4144c..6bf510702b 100644
--- a/Documentation/git-stash.adoc
+++ b/Documentation/git-stash.adoc
@@ -18,8 +18,6 @@ git stash [push] [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | -
 	     [-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
 	     [--pathspec-from-file=<file> [--pathspec-file-nul]]
 	     [--] [<pathspec>...]
-git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
-           [-u | --include-untracked] [-a | --all] [<message>]
 git stash clear
 git stash create [<message>]
 git stash store [(-m | --message) <message>] [-q | --quiet] <commit>
diff --git a/builtin/stash.c b/builtin/stash.c
index 7a9843413b..94869c2429 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -75,7 +75,6 @@ static const char * const git_stash_usage[] = {
 	BUILTIN_STASH_APPLY_USAGE,
 	BUILTIN_STASH_BRANCH_USAGE,
 	BUILTIN_STASH_PUSH_USAGE,
-	BUILTIN_STASH_SAVE_USAGE,
 	BUILTIN_STASH_CLEAR_USAGE,
 	BUILTIN_STASH_CREATE_USAGE,
 	BUILTIN_STASH_STORE_USAGE,
-- 
2.56.0.237.g5414b88716.dirty
D. Ben Knoble· Oct 23, 2026, 13:20 UTC · re: D. Ben Knoble · lore

[PATCH v2 5/5] completion: drop "stash save" completion altogether

It's been deprecated since fd2ebf14db (stash: mark "git stash save" deprecated in the man page, 2017-10-22) and the previous commit removed further documentation suggesting to use it.

Since we recommend push instead, stop completing for "save" and remove a special case in completion code. It still appears for "git stash <tab>" when GIT_COMPLETION_SHOW_ALL=1, and when typed explicitly we still complete options for

    git stash save --<tab>
which is helpful for folks with finger-memory for save.
Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
---
 contrib/completion/git-completion.bash | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)
Show changes to contrib/completion/git-completion.bash +1 −4
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 697fef5462..9cd9c7cadb 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3558,16 +3558,13 @@ _git_stash ()
 	__git_resolve_builtins stash
 
 	subcommands="$___git_resolved_builtins"
-	subcommand="$(__git_find_on_cmdline "$subcommands save")"
+	subcommand="$(__git_find_on_cmdline "$subcommands")"
 
 	if [ -z "$subcommand" ]; then
 		case "$((cword - __git_cmd_idx)),$cur" in
 		*,--*)
 			__gitcomp_builtin stash_push
 			;;
-		1,sa*)
-			__gitcomp "save"
-			;;
 		1,*)
 			__gitcomp "$subcommands"
 			;;
-- 
2.56.0.237.g5414b88716.dirty
Junio C Hamano· Oct 23, 2026, 17:06 UTC · re: D. Ben Knoble · lore

Re: [PATCH v2 5/5] completion: drop "stash save" completion altogether

"D. Ben Knoble" <ben.knoble@gmail.com> writes:
Show 12 quoted lines
> It's been deprecated since fd2ebf14db (stash: mark "git stash save"
> deprecated in the man page, 2017-10-22) and the previous commit removed
> further documentation suggesting to use it.
>
> Since we recommend push instead, stop completing for "save" and remove a
> special case in completion code. It still appears for "git stash <tab>"
> when GIT_COMPLETION_SHOW_ALL=1, and when typed explicitly we still
> complete options for
>
>     git stash save --<tab>
>
> which is helpful for folks with finger-memory for save.

Well, if we can replace the command line to "git stash push --" on the first <tab> and then start completing for "stash push" with the second <tab>, it would be superb.

Show 19 quoted lines
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 697fef5462..9cd9c7cadb 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -3558,16 +3558,13 @@ _git_stash ()
>  	__git_resolve_builtins stash
>  
>  	subcommands="$___git_resolved_builtins"
> -	subcommand="$(__git_find_on_cmdline "$subcommands save")"
> +	subcommand="$(__git_find_on_cmdline "$subcommands")"
>  
>  	if [ -z "$subcommand" ]; then
>  		case "$((cword - __git_cmd_idx)),$cur" in
>  		*,--*)
>  			__gitcomp_builtin stash_push
>  			;;
> -		1,sa*)
> -			__gitcomp "save"
> -			;;

Nice to see this go. This would have been maintenance nightmare if left forever as we will have to remember updating it when "sa" no longer becomes a unique prefix.

Ben Knoble· Oct 23, 2026, 18:07 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 5/5] completion: drop "stash save" completion altogether

Show 20 quoted lines
> Le 23 oct. 2026 à 13:06, Junio C Hamano <gitster@pobox.com> a écrit :
> 
> "D. Ben Knoble" <ben.knoble@gmail.com> writes:
> 
>> It's been deprecated since fd2ebf14db (stash: mark "git stash save"
>> deprecated in the man page, 2017-10-22) and the previous commit removed
>> further documentation suggesting to use it.
>> 
>> Since we recommend push instead, stop completing for "save" and remove a
>> special case in completion code. It still appears for "git stash <tab>"
>> when GIT_COMPLETION_SHOW_ALL=1, and when typed explicitly we still
>> complete options for
>> 
>>    git stash save --<tab>
>> 
>> which is helpful for folks with finger-memory for save.
> 
> Well, if we can replace the command line to "git stash push --" on
> the first <tab> and then start completing for "stash push" with the
> second <tab>, it would be superb.

We probably can (I know Zsh is capable), but that means more complex special-casing ;) I’d rather get rid of this case and leave that nicety for someone who’s motivated to get consensus for it, which I am not.

Show 24 quoted lines
> 
>> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
>> index 697fef5462..9cd9c7cadb 100644
>> --- a/contrib/completion/git-completion.bash
>> +++ b/contrib/completion/git-completion.bash
>> @@ -3558,16 +3558,13 @@ _git_stash ()
>>    __git_resolve_builtins stash
>> 
>>    subcommands="$___git_resolved_builtins"
>> -    subcommand="$(__git_find_on_cmdline "$subcommands save")"
>> +    subcommand="$(__git_find_on_cmdline "$subcommands")"
>> 
>>    if [ -z "$subcommand" ]; then
>>        case "$((cword - __git_cmd_idx)),$cur" in
>>        *,--*)
>>            __gitcomp_builtin stash_push
>>            ;;
>> -        1,sa*)
>> -            __gitcomp "save"
>> -            ;;
> 
> Nice to see this go.  This would have been maintenance nightmare if
> left forever as we will have to remember updating it when "sa" no
> longer becomes a unique prefix.
Kristoffer Haugsbakk· Oct 23, 2026, 14:33 UTC · re: D. Ben Knoble · lore

Re: [PATCH v2 0/5] stash completion miscellany

On Fri, Oct 23, 2026, at 15:20, D. Ben Knoble wrote:
Show 17 quoted lines
> This short patch series takes care of a few paper cuts in stash
> completion. The first patch is a small code cleanup I noticed a while
> back while working on bfc1b34859 (completion: add stash import, export,
> 2026-02-07), I think. The next 2 take care of a problem I've been having
> with Zsh's completion of stashes (cf. Unix & Linux SE [1]).
>
> [1]: https://unix.stackexchange.com/q/807580/301073
>
>[snip]
>
> Generated-with: git format-patch @{u}.. -o p -v2
> --range-diff=@{u}..d1d0bf2d9a7d380d10771b5d1bceb8db91c5f05e
> --in-reply-to=cover.1791827304.git.ben.knoble@gmail.com --cc='Patrick
> Steinhardt <ps@pks.im>'
>
> I accidentally left the above line in v1, but I'm considering leaving it in from
> now on?
;)
Show 14 quoted lines
> It's the exact command I run to generate patches; I store it as a
> "trailer" in the branch description, then run "git generated-with"† which
> (effectively) does
>
>     eval "$(git bdesc | git interpret-trailers --parse | grep
> ^Generated-with | cut -d: -f 2-)"
>
> where "bdesc" is an alias for
>
>     git -c core.editor=cat branch --edit-description | git stripspace -s
>
> Anyway, I've been hand-editing them out of cover letters for the last few
> series, but if it doesn't bother anyone I'll just leave it around. Might be
> helpful for new folks learning how to format patches?
I think it’s a decent-to-good idea to leave it in.
>
> †:
> https://github.com/benknoble/Dotfiles/blob/master/links/bin/git-generated-with
>[snip]
Patrick Steinhardt· Oct 26, 2026, 08:48 UTC · re: D. Ben Knoble · lore

Re: [PATCH v2 0/5] stash completion miscellany

On Fri, Oct 23, 2026 at 09:20:50AM -0400, D. Ben Knoble wrote:
Show 12 quoted lines
> Diff-intervalle contre v1 :
> 1:  d0e461a14a ! 1:  90d36b6445 completion: simplify stash subcommand completion
>     @@ Commit message
>          The stash completion helper contains a hard-coded list of commands, but
>          git-stash provides a mechanism to list such commands
>          (--git-completion-helper). The pattern for using it is wrapped by
>     -    __git_resolve_builtins, so use it, bring _git_stash closer in line with
>     -    other completion helpers.
>     +    __git_resolve_builtins, so use it, bringing _git_stash closer in line
>     +    with other completion helpers. As a nice side-benefit, this also adds
>     +    "store" subcommand completion, which is missing from the explicit list
>     +    of subcommands.
Yup.
Show 13 quoted lines
>     -    Note that we maintain the "save" special case, since it was removed from
>     +    Note that we maintain the "save" special case†, since it was removed from
>          default completion in 0eb5a4f911 (completion: stop showing 'save' for
>     -    stash by default, 2018-04-20). We don't have to do anything special with
>     -    the exclude (3rd) argument to __git_resolve_builtins, though, because
>     -    save is already marked PARSE_OPT_NOCOMPLETE.
>     +    stash by default, 2018-04-20). One might think we need to give "save" to
>     +    __git_resolve_builtins' 3rd exclude argument to prevent it from
>     +    showing up, but we don't: "save" is already marked PARSE_OPT_NOCOMPLETE.
>     +
>     +    †We don't complete the "save" subcommand unless at least "sa" has been
>     +    typed, but we do complete its options if explicitly typed. With this
>     +    change, we will complete "save" if GIT_COMPLETION_SHOW_ALL=1.
Good.
Show 13 quoted lines
> 5:  d1d0bf2d9a ! 5:  0266646fb4 completion: drop "stash save" completion altogether
>     @@ Commit message
>          further documentation suggesting to use it.
>      
>          Since we recommend push instead, stop completing for "save" and remove a
>     -    special case in completion code.
>     +    special case in completion code. It still appears for "git stash <tab>"
>     +    when GIT_COMPLETION_SHOW_ALL=1, and when typed explicitly we still
>     +    complete options for
>     +
>     +        git stash save --<tab>
>     +
>     +    which is helpful for folks with finger-memory for save.
Agreed, documenting the status quo feels reasonable to me.
So overall I'm happy with this v2, thanks!
Patrick
Junio C Hamano· Oct 26, 2026, 14:30 UTC · re: Patrick Steinhardt · lore

Re: [PATCH v2 0/5] stash completion miscellany

Patrick Steinhardt <ps@pks.im> writes:
Show 12 quoted lines
>>     -    special case in completion code.
>>     +    special case in completion code. It still appears for "git stash <tab>"
>>     +    when GIT_COMPLETION_SHOW_ALL=1, and when typed explicitly we still
>>     +    complete options for
>>     +
>>     +        git stash save --<tab>
>>     +
>>     +    which is helpful for folks with finger-memory for save.
>
> Agreed, documenting the status quo feels reasonable to me.
>
> So overall I'm happy with this v2, thanks!
Thanks for writing and reviewing.

← back to recent threads