Re: [PATCH] completion: complete paths for git send-email
From: D. Ben Knoble
Date: Tue Jul 21 2026 - 08:56:49 EST
On Sun, Jul 19, 2026 at 9:45 AM Yury Norov (NVIDIA)
<yury.norov@xxxxxxxxx> wrote:
>
> From: Yury Norov <ynorov@xxxxxxxxxx>
>
> git send-email accepts either revisions or paths to patch files, but its
> Bash completion only offers revisions. This prevents patch files from
> being completed. It can also make a prefix such as "0" expand to an
> unrelated hexadecimal ref even when matching 0001-*.patch files exist.
>
> In my Linux tree, an attempt to autocomplete the standard-named patch
> brings a random hashtag:
It is unusual to call this a "hashtag." Perhaps "hash" or "object
name" (or id) based on the glossary and datamodel docs?
> $ ls 0*
> 0001-bitmap-drop-bitmap_next_set_region.patch
> $ git send-email 0<Tab>
> $ git send-email 05c69d298c96703741cac9a5cbbf6c53bd55a6e2
>
> Introduce an append variant of __gitcomp_file() and use it to add
> filesystem candidates after the existing revision candidates. Keep the
> latter because revisions remain valid send-email arguments.
>
> Add a regression test covering patch files alongside a 40-hex ref.
>
> Assisted-by: Codex <codex@xxxxxxxxxx>
> Signed-off-by: Yury Norov <ynorov@xxxxxxxxxx>
> ---
> contrib/completion/git-completion.bash | 29 +++++++++++++++++++-------
> t/t9902-completion.sh | 12 ++++++++++-
> 2 files changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index e87578771..b7017488d 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -579,21 +579,18 @@ __gitcomp_file_direct ()
> }
>
> # Generates completion reply with compgen from newline-separated possible
> -# completion filenames.
> +# completion filenames by appending them to the existing list of completion
> +# candidates, COMPREPLY.
> # It accepts 1 to 3 arguments:
> # 1: List of possible completion filenames, separated by a single newline.
> # 2: A directory prefix to be added to each possible completion filename
> # (optional).
> # 3: Generate possible completion matches for this word (optional).
> -__gitcomp_file ()
> +__gitcomp_file_append ()
> {
> local IFS=$'\n'
>
> - # XXX does not work when the directory prefix contains a tilde,
> - # since tilde expansion is not applied.
> - # This means that COMPREPLY will be empty and Bash default
> - # completion will be used.
> - __gitcompadd "$1" "${2-}" "${3-$cur}" ""
> + __gitcompappend "$1" "${2-}" "${3-$cur}" ""
>
> # use a hack to enable file mode in bash < 4
> compopt -o filenames +o nospace 2>/dev/null ||
> @@ -601,6 +598,23 @@ __gitcomp_file ()
> true
> }
>
> +# Generates completion reply with compgen from newline-separated possible
> +# completion filenames.
> +# It accepts 1 to 3 arguments:
> +# 1: List of possible completion filenames, separated by a single newline.
> +# 2: A directory prefix to be added to each possible completion filename
> +# (optional).
> +# 3: Generate possible completion matches for this word (optional).
> +__gitcomp_file ()
> +{
> + # XXX does not work when the directory prefix contains a tilde,
> + # since tilde expansion is not applied.
> + # This means that COMPREPLY will be empty and Bash default
> + # completion will be used.
> + COMPREPLY=()
> + __gitcomp_file_append "$@"
> +}
> +
Curious; the diff itself is much more readable for me when applied
locally (it shows the addition of __gitcomp_file_append and the
replacement of a few lines in __gitcomp_file).
Nonetheless, this follows the pattern established by __gitcompadd and
__gitcompappend, so that part at least looks like it functions as
expected. (I can't comment too much on the code that existed there
already.)
> # Find the current subcommand for commands that follow the syntax:
> #
> # git <command> <subcommand>
> @@ -2634,6 +2648,7 @@ _git_send_email ()
> ;;
> esac
> __git_complete_revlist
> + __gitcomp_file_append "$(compgen -f -- "$cur")"
At least with Bash with compgen, this looks to me like it does append
file names to the COMPREPLY.
But, with the "hack" comment in the modified function, do we also need
to account for older bash? It looks like that comes from 3ffa4df4b2
(completion: add hack to enable file mode in bash < 4, 2013-04-27).
After studying a bit more, that hack is to make Bash do the right
thing during file completion, not to workaround different methods of
generating filenames (unlike Zsh, which has a newer and an older
completion system, Bash's seems relatively stable?).
So, I think this looks good.
> }
>
> _git_stage ()
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index 55dc9eabf..e87827f21 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2777,7 +2777,17 @@ test_expect_success PERL 'send-email' '
> test_completion "git send-email --val" <<-\EOF &&
> --validate Z
> EOF
> - test_completion "git send-email ma" "main "
> + test_completion "git send-email ma" "main " &&
> +
> + git tag 05c69d298c96703741cac9a5cbbf6c53bd55a6e2 &&
> + test_when_finished "git tag -d 05c69d298c96703741cac9a5cbbf6c53bd55a6e2 &&
> + rm -f 0001-example.patch 0002-example.patch" &&
> + touch 0001-example.patch 0002-example.patch &&
> + test_completion "git send-email 0" <<-\EOF
> + 0001-example.patch
> + 0002-example.patch
> + 05c69d298c96703741cac9a5cbbf6c53bd55a6e2 Z
> + EOF
> '
>
> test_expect_success 'complete files' '
> --
> 2.53.0
Junio commented on the test, so I'll stop here.
Pending a commit message tweak for "hashtag," I'm satisfied enough for
Reviewed-by: D. Ben Knoble <ben.knoble@xxxxxxxxx>
(Or feel free to use "Acked-by" if this is not a strong enough review
for you/the project!)
--
D. Ben Knoble