From 652d690fc3c1862803624fb0e63071ee5649334d Mon Sep 17 00:00:00 2001 From: "D. Ben Knoble" Date: Fri, 23 Oct 2026 09:20:51 -0400 Subject: [PATCH 1/5] completion: simplify stash subcommand completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 From 76fa9f70f151463895e5e74d0ca5319fb714339c Mon Sep 17 00:00:00 2001 From: "D. Ben Knoble" Date: Fri, 23 Oct 2026 09:20:52 -0400 Subject: [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 Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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 From 9703e2604cc76fcf7bf05bad8511928f966cf660 Mon Sep 17 00:00:00 2001 From: "D. Ben Knoble" Date: Fri, 23 Oct 2026 09:20:53 -0400 Subject: [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 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 Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.zsh | 5 +++++ 1 file changed, 5 insertions(+) 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" From 0a93af805397774bfe28e7950e22436e9e7f6456 Mon Sep 17 00:00:00 2001 From: "D. Ben Knoble" Date: Fri, 23 Oct 2026 09:20:54 -0400 Subject: [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 Signed-off-by: Junio C Hamano --- Documentation/git-stash.adoc | 2 -- builtin/stash.c | 1 - 2 files changed, 3 deletions(-) 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) ] [--pathspec-from-file= [--pathspec-file-nul]] [--] [...] -git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet] - [-u | --include-untracked] [-a | --all] [] git stash clear git stash create [] git stash store [(-m | --message) ] [-q | --quiet] 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, From 1ae1ddeba3fbc3295a5984c8b232ecd737e69192 Mon Sep 17 00:00:00 2001 From: "D. Ben Knoble" Date: Fri, 23 Oct 2026 09:20:55 -0400 Subject: [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. It still appears for "git stash " when GIT_COMPLETION_SHOW_ALL=1, and when typed explicitly we still complete options for git stash save -- which is helpful for folks with finger-memory for save. Signed-off-by: D. Ben Knoble Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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" ;;