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

[PATCH v4 0/3] completion of 'git [-C <dir>] diff'

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 7, 2026, 01:38 UTC
Message-ID
<20260807013830.698340-1-gitster@pobox.com>
In-Reply-To
<xmqqcxw010me.fsf@gitster.g>

The primary motivation for this topic is that the command-line completion of 'git diff' does not handle paths (unlike 'git status' and 'git add') and instead relies on the default behavior of Bash command-line completion, which completes files in $PWD; this does not work at all with the '-C <directory>' option.

This series teaches the completion machinery to complete revisions (unless '--' exists), then tracked paths, and then untracked paths, before letting the Bash default kick in. This way, we correctly complete 'git diff' command line even when '-C <directory>' is in effect.

The tests are the only changes relative to v2. In the step where tracked paths are completed, v2 did not demonstrate that untracked ones are *not* completed at the same time. Now we do by having untracked 'file3' next to 'file1' and 'file2' that are tracked. In the last step, we demonstrate untracked paths that do not share prefix with refs or tracked paths are completed, with or without the "-C <dir>" option.

 1/3: completion: no-op refactoring of diff completion
 2/3: completion: complete tracked paths for 'git diff'
 3/3: completion: 'git diff' completes untracked paths as a last
        resort
 contrib/completion/git-completion.bash | 69 +++++++++++++++-----------
 t/t9902-completion.sh                  | 49 ++++++++++++++++++
 2 files changed, 90 insertions(+), 28 deletions(-)
Range-diff against v3:
1:  d3c51c042c = 1:  3b99b45fee completion: no-op refactoring of diff completion
2:  c3658d6ca2 ! 2:  bcc24b6bda completion: complete tracked paths for 'git diff'
    @@ contrib/completion/git-completion.bash: _git_diff ()
      __git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff
     
      ## t/t9902-completion.sh ##
    +@@ t/t9902-completion.sh: 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
     @@ t/t9902-completion.sh: 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
    ++	# there is no ref that begins with f
    ++	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_expect_success 'git -C <path> diff completes in the specified repo' '
     +	test_when_finished "rm -rf repo-for-diff" &&
     +	git init repo-for-diff &&
    ++
    ++	# otherfile is tracked, oops is untracked
     +	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
    ++	echo untracked >repo-for-diff/oops &&
    ++	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
3:  ba5dc6f164 ! 3:  34720a30ab completion: 'git diff' completes untracked paths as a last resort
    @@ contrib/completion/git-completion.bash: _git_diff ()
     
      ## t/t9902-completion.sh ##
     @@ t/t9902-completion.sh: test_expect_success 'setup for integration tests' '
    - 	echo content >file1 &&
      	echo more >file2 &&
      	git add file1 file2 &&
    + 	echo untracked >file3 &&
     +	echo untracked >ufile &&
      	git commit -m one &&
      	git branch mybranch &&
      	git tag mytag
    -@@ t/t9902-completion.sh: test_expect_success 'git diff -- completes tracked paths' '
    +@@ t/t9902-completion.sh: test_expect_success 'git diff completes tracked paths when no refs match' '
      	EOF
      '
      
     +test_expect_success 'git diff [--] completes untracked paths, too' '
    ++	# there is no ref or tracked path that begin with u
     +	test_completion "git diff u" <<-\EOF &&
     +	ufile
     +	EOF
    @@ t/t9902-completion.sh: test_expect_success 'git diff -- completes tracked paths'
     +	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 &&
    -@@ t/t9902-completion.sh: test_expect_success 'git -C <path> diff -- completes pathspecs in specified repo
    + test_expect_success 'git -C <path> diff completes in the specified repo' '
      	test_when_finished "rm -rf repo-for-diff" &&
      	git init repo-for-diff &&
    + 
    +-	# otherfile is tracked, oops is untracked
    ++	# otherfile is tracked, oops and ufile are untracked
      	echo content >repo-for-diff/otherfile &&
    -+	echo untracked >repo-for-diff/untracked &&
      	git -C repo-for-diff add otherfile &&
      	git -C repo-for-diff commit -m otherfile &&
    + 	echo untracked >repo-for-diff/oops &&
    ++	echo untracked >repo-for-diff/ufile &&
    + 	test_completion "git -C repo-for-diff diff o" <<-\EOF &&
    + 	otherfile
    + 	EOF
     -	test_completion "git -C repo-for-diff diff -- o" <<-\EOF
    -+	test_completion "git -C repo-for-diff diff o" <<-\EOF &&
    -+	otherfile
    -+	EOF
     +	test_completion "git -C repo-for-diff diff -- o" <<-\EOF &&
      	otherfile
      	EOF
     +	test_completion "git -C repo-for-diff diff u" <<-\EOF &&
    -+	untracked
    ++	ufile
     +	EOF
     +	test_completion "git -C repo-for-diff diff -- u" <<-\EOF
    -+	untracked
    ++	ufile
     +	EOF
      '
      
-- 
2.55.0-655-gb2c071042d
Previous: D. Ben KnobleNext: Junio C Hamano
Message 14 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.