git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] completion: complete tracked paths for 'git diff'

From
SZEDER Gábor <szeder.dev@gmail.com>
Date
Aug 3, 2026, 05:44 UTC
Message-ID
<anAqfqcEueSKmAH+@szeder.dev>
In-Reply-To
<xmqqcxw010me.fsf@gitster.g>
On Sun, Aug 02, 2026 at 05:58:01PM -0700, Junio C Hamano wrote:
Show 13 quoted lines
> When completing arguments for 'git diff', _git_diff() delegates to
> __git_complete_revlist_file(), which only completes revision
> references.  This is good [*], as mixing both revs and paths in a
> single list to have the user pick is simply too confusing.
> 
> If no reference matches, or if '--' is given, however, _git_diff()
> leaves COMPREPLY empty. Bash then falls back to default filename
> completion in $PWD. This fails when 'git -C <path>' is used because
> $PWD is not the target repository.
> 
> Update _git_diff() to use __git_complete_index_file() when '--' is
> present, or when revision reference completion yields no matching
> candidates, so that tracked paths are offered as candidates.
Makes sense.
Show 14 quoted lines
> [Footnote]
> 
>  * In https://lore.kernel.org/git/al%2Fw2qgBfhe9qMg6@szeder.dev/
>    SZEDER made the same argument for "git send-email 0<TAB>".
> 
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
> 
>  * This is one of my pet peeves that I have raised a few times on
>    the list but nobody reacted.  So I did a "monkey see, monkey do"
>    patch without deeply understanding what is going on in the code
>    paths.  When preparing the CC: list, I pulled a few folks, some
>    very recognizable, some not recognizable immediately by me, out
>    of "git shortlog --since=3.years" on this file.

Will have to finally polish and submit a completion patch from my vaults to get myself back on this list ;)

>    The contribution
>    by any of them looked more expertly done by whatever I did here.
I think your changes are fine.

However, there is 'git diff --no-index' which happily accepts untracked files as well, but with this patch the user can complete only those untracked files that don't match the current word on the command line (because then __git_complete_index_file() won't list anything, and we'll fall back to Bash filename completion like before).

I think we should check whether the '--no-index' option is present on the command line, and simply not call __git_complete_index_file() if it is, to let Bash list all paths; i.e. each of those calls should be protected by an additional 'if test -z "$(__git_find_on_cmdline "--no-index")' condition, perhaps.

Show 102 quoted lines
>    The use case is that I have a checkout of the 'todo' branch in an
>    untracked subdirectory 'Meta' in my primary source tree.  I would
>    do
> 
>     $ git -C Meta status wh<TAB>
> 
>    and it completes to whats-cooking.txt just fine, 'add' also adds
>    it, but 'diff' dies not work, not because I have refs that 'wh'
>    completes, but because bash completion is unaware that I want
>    paths completed in the other directory.
> 
>  contrib/completion/git-completion.bash |  8 +++++-
>  t/t9902-completion.sh                  | 40 ++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+), 1 deletion(-)
> 
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index e875787710..8f5773292b 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1947,7 +1947,10 @@ __git_diff_difftool_options="--cached --staged
>  
>  _git_diff ()
>  {
> -	__git_has_doubledash && return
> +	if __git_has_doubledash; then
> +		__git_complete_index_file
> +		return
> +	fi
>  
>  	case "$cur" in
>  	--diff-algorithm=*)
> @@ -1976,6 +1979,9 @@ _git_diff ()
>  		;;
>  	esac
>  	__git_complete_revlist_file
> +	if [ ${#COMPREPLY[@]} -eq 0 ]; then
> +		__git_complete_index_file
> +	fi
>  }
>  
>  __git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index 55dc9eabfc..eecd53f097 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2663,6 +2663,7 @@ test_expect_success 'setup for integration tests' '
>  	echo content >file1 &&
>  	echo more >file2 &&
>  	git add file1 file2 &&
> +	echo untracked >file3 &&
>  	git commit -m one &&
>  	git branch mybranch &&
>  	git tag mytag
> @@ -2712,6 +2713,45 @@ test_expect_success 'git -C <path> checkout uses the right repo' '
>  	EOF
>  '
>  
> +test_expect_success 'git diff completes tracked paths when no refs match' '
> +	# file1 and file2 are tracked but file3 is not
> +	test_completion "git diff f" <<-\EOF
> +	file1
> +	file2
> +	EOF
> +'
> +
> +test_expect_success 'git diff -- completes tracked paths' '
> +	# file1 and file2 are tracked but file3 is not
> +	test_completion "git diff -- f" <<-\EOF
> +	file1
> +	file2
> +	EOF
> +'
> +
> +test_expect_success 'git -C <path> diff completes tracked paths in specified repo' '
> +	test_when_finished "rm -rf repo-for-diff" &&
> +	git init repo-for-diff &&
> +	echo content >repo-for-diff/otherfile &&
> +	git -C repo-for-diff add otherfile &&
> +	echo untracked >repo-for-diff/oops &&
> +	git -C repo-for-diff commit -m otherfile &&
> +	test_completion "git -C repo-for-diff diff o" <<-\EOF
> +	otherfile
> +	EOF
> +'
> +
> +test_expect_success 'git -C <path> diff -- completes pathspecs in specified repo' '
> +	test_when_finished "rm -rf repo-for-diff" &&
> +	git init repo-for-diff &&
> +	echo content >repo-for-diff/otherfile &&
> +	git -C repo-for-diff add otherfile &&
> +	git -C repo-for-diff commit -m otherfile &&
> +	test_completion "git -C repo-for-diff diff -- o" <<-\EOF
> +	otherfile
> +	EOF
> +'
> +
>  test_expect_success 'show completes all refs' '
>  	test_completion "git show m" <<-\EOF
>  	main Z
> -- 
> 2.55.0-607-g47e9082d35
> 
Previous: Junio C HamanoNext: Junio C Hamano
Message 3 of 34 in “completion: complete tracked paths for 'git diff'”
  1. completion: complete tracked paths for 'git diff'Junio C Hamano, Aug 3, 2026
  2. Junio C HamanoAug 3, 2026
  3. SZEDER GáborAug 3, 2026
  4. Junio C HamanoAug 3, 2026
  5. Junio C HamanoAug 3, 2026
  6. completion: complete tracked paths for 'git diff'Junio C Hamano, Aug 4, 2026
  7. 0/3 completion of 'git [-C <dir>] diff'Junio C Hamano, Aug 5, 2026
  8. 1/3 completion: no-op refactoring of diff completionJunio C Hamano, Aug 5, 2026
  9. 2/3 completion: complete tracked paths for 'git diff'Junio C Hamano, Aug 5, 2026
  10. 3/3 completion: 'git diff' completes untracked paths as a last resortJunio C Hamano, Aug 5, 2026
  11. D. Ben KnobleAug 6, 2026
  12. Junio C HamanoAug 6, 2026
  13. D. Ben KnobleAug 6, 2026
  14. 0/3 completion of 'git [-C <dir>] diff'Junio C Hamano, Aug 7, 2026
  15. 1/3 completion: no-op refactoring of diff completionJunio C Hamano, Aug 7, 2026
  16. Elijah NewrenAug 7, 2026
  17. Junio C HamanoAug 7, 2026
  18. 3/3 completion: 'git diff' completes untracked paths as a last resortJunio C Hamano, Aug 7, 2026
  19. 2/3 completion: complete tracked paths for 'git diff'Junio C Hamano, Aug 7, 2026
  20. Elijah NewrenAug 7, 2026
  21. D. Ben KnobleAug 7, 2026
  22. Junio C HamanoAug 7, 2026
  23. Elijah NewrenAug 7, 2026
  24. Elijah NewrenAug 7, 2026
  25. D. Ben KnobleAug 7, 2026
  26. 0/3 completion of 'git [-C <dir>] diff'Junio C Hamano, Aug 7, 2026
  27. 1/3 completion: no-op refactoring of diff completionJunio C Hamano, Aug 7, 2026
  28. 2/3 completion: complete tracked paths for 'git diff'Junio C Hamano, Aug 7, 2026
  29. 3/3 completion: 'git diff' completes untracked paths as a last resortJunio C Hamano, Aug 7, 2026
  30. Elijah NewrenAug 7, 2026
  31. 0/3 completion of 'git [-C <dir>] diff'Junio C Hamano, Aug 12, 2026
  32. 1/3 completion: no-op refactoring of diff completionJunio C Hamano, Aug 12, 2026
  33. 2/3 completion: complete tracked paths for 'git diff'Junio C Hamano, Aug 12, 2026
  34. 3/3 completion: 'git diff' completes untracked paths as a last resortJunio C Hamano, Aug 12, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.