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

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

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 12, 2026, 16:25 UTC
Message-ID
<20260812162551.2229680-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 changes since v5 are all concentrated in the tests. They test the same thing, but organized in a more logical and regular way.

This round hopefully will be the last one (famous last words).
 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                  | 58 ++++++++++++++++++++++
 2 files changed, 99 insertions(+), 28 deletions(-)
Range-diff against v5:
1:  74bfe67e24 = 1:  a5b2bdcd21 completion: no-op refactoring of diff completion
2:  f6892a66e9 ! 2:  cb84c1407c 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 paths in specified repo' '
     +	test_when_finished "rm -rf repo-for-diff" &&
     +	git init repo-for-diff &&
     +	echo content >repo-for-diff/otherfile &&
    ++	echo content >repo-for-diff/lostfile &&
     +	git -C repo-for-diff add otherfile &&
    -+	echo untracked >repo-for-diff/oops &&
    ++	git -C repo-for-diff add lostfile &&
     +	git -C repo-for-diff commit -m otherfile &&
    -+	test_completion "git -C repo-for-diff diff o" <<-\EOF
    ++	echo untracked >repo-for-diff/oops &&
    ++	rm -f repo-for-diff/lostfile &&
    ++
    ++	test_completion "git -C repo-for-diff diff o" <<-\EOF &&
     +	otherfile
     +	EOF
    -+'
    ++	test_completion "git -C repo-for-diff diff l" <<-\EOF &&
    ++	lostfile
    ++	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
    ++	test_completion "git -C repo-for-diff diff -- o" <<-\EOF &&
     +	otherfile
     +	EOF
    ++	test_completion "git -C repo-for-diff diff -- l" <<-\EOF
    ++	lostfile
    ++	EOF
     +'
     +
      test_expect_success 'show completes all refs' '
3:  dcc5f881f2 ! 3:  d73c18e876 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' '
    ++	# ufile is not tracked and there is no ref that begins 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_expect_success 'git -C <path> diff completes 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_when_finished "rm -rf repo-for-diff" &&
    - 	git init repo-for-diff &&
    - 	echo content >repo-for-diff/otherfile &&
    -+	echo untracked >repo-for-diff/untracked &&
    - 	git -C repo-for-diff add otherfile &&
    +@@ t/t9902-completion.sh: test_expect_success 'git -C <path> diff completes paths in specified repo' '
    + 	git -C repo-for-diff add lostfile &&
      	git -C repo-for-diff commit -m otherfile &&
    --	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
    + 	echo untracked >repo-for-diff/oops &&
    ++	echo untracked >repo-for-diff/ufile &&
    + 	rm -f repo-for-diff/lostfile &&
    + 
    + 	test_completion "git -C repo-for-diff diff o" <<-\EOF &&
    +@@ t/t9902-completion.sh: test_expect_success 'git -C <path> diff completes paths in specified repo' '
    + 	test_completion "git -C repo-for-diff diff l" <<-\EOF &&
    + 	lostfile
      	EOF
     +	test_completion "git -C repo-for-diff diff u" <<-\EOF &&
    -+	untracked
    ++	ufile
     +	EOF
    + 
    + 	test_completion "git -C repo-for-diff diff -- o" <<-\EOF &&
    + 	otherfile
    + 	EOF
    +-	test_completion "git -C repo-for-diff diff -- l" <<-\EOF
    ++	test_completion "git -C repo-for-diff diff -- l" <<-\EOF &&
    + 	lostfile
    + 	EOF
     +	test_completion "git -C repo-for-diff diff -- u" <<-\EOF
    -+	untracked
    ++	ufile
     +	EOF
      '
      
-- 
2.55.0-721-gd75157efe4
Previous: Elijah NewrenNext: Junio C Hamano
Message 31 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.