From: Junio C Hamano Date: Wed, 12 Aug 2026 16:25:48 GMT Subject: [PATCH v6 0/3] completion of 'git [-C ] diff' Message-ID: <20260812162551.2229680-1-gitster@pobox.com> In-Reply-To: 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 ' 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 ' 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 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 diff completes tracked paths in specified repo' ' ++test_expect_success 'git -C 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 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 diff completes tracked paths in specified repo' ' + test_expect_success 'git -C 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 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 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 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