From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Cc: "Philippe Blain" <levraiphilippeblain@gmail.com>,
"Britton Leo Kerin" <britton.kerin@gmail.com>,
"Elijah Newren" <newren@gmail.com>,
"Rubén Justo" <rjusto@gmail.com>,
"Patrick Steinhardt" <ps@pks.im>,
"D. Ben Knoble" <ben.knoble@gmail.com>,
"SZEDER Gábor" <szeder.dev@gmail.com>
Subject: [PATCH v6 0/3] completion of 'git [-C <dir>] diff'
Date: Wed, 12 Aug 2026 09:25:48 -0700 [thread overview]
Message-ID: <20260812162551.2229680-1-gitster@pobox.com> (raw)
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
next prev parent reply other threads:[~2026-08-12 16:25 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-03 0:58 [PATCH] completion: complete tracked paths for 'git diff' Junio C Hamano
2026-08-03 1:07 ` Junio C Hamano
2026-08-03 5:44 ` SZEDER Gábor
2026-08-03 13:41 ` Junio C Hamano
2026-08-03 15:45 ` Junio C Hamano
2026-08-04 16:22 ` [PATCH v2] " Junio C Hamano
2026-08-05 19:42 ` [PATCH v3 0/3] completion of 'git [-C <dir>] diff' Junio C Hamano
2026-08-05 19:42 ` [PATCH v3 1/3] completion: no-op refactoring of diff completion Junio C Hamano
2026-08-05 19:42 ` [PATCH v3 2/3] completion: complete tracked paths for 'git diff' Junio C Hamano
2026-08-05 19:42 ` [PATCH v3 3/3] completion: 'git diff' completes untracked paths as a last resort Junio C Hamano
2026-08-06 11:30 ` D. Ben Knoble
2026-08-06 15:06 ` Junio C Hamano
2026-08-06 11:30 ` [PATCH v3 0/3] completion of 'git [-C <dir>] diff' D. Ben Knoble
2026-08-07 1:38 ` [PATCH v4 " Junio C Hamano
2026-08-07 1:38 ` [PATCH v4 1/3] completion: no-op refactoring of diff completion Junio C Hamano
2026-08-07 6:15 ` Elijah Newren
2026-08-07 15:09 ` Junio C Hamano
2026-08-07 1:38 ` [PATCH v4 2/3] completion: complete tracked paths for 'git diff' Junio C Hamano
2026-08-07 6:18 ` Elijah Newren
2026-08-07 11:02 ` D. Ben Knoble
2026-08-07 15:13 ` Junio C Hamano
2026-08-07 15:22 ` Elijah Newren
2026-08-07 1:38 ` [PATCH v4 3/3] completion: 'git diff' completes untracked paths as a last resort Junio C Hamano
2026-08-07 6:31 ` [PATCH v4 0/3] completion of 'git [-C <dir>] diff' Elijah Newren
2026-08-07 11:05 ` D. Ben Knoble
2026-08-07 16:19 ` [PATCH v5 " Junio C Hamano
2026-08-07 16:19 ` [PATCH v5 1/3] completion: no-op refactoring of diff completion Junio C Hamano
2026-08-07 16:19 ` [PATCH v5 2/3] completion: complete tracked paths for 'git diff' Junio C Hamano
2026-08-07 16:19 ` [PATCH v5 3/3] completion: 'git diff' completes untracked paths as a last resort Junio C Hamano
2026-08-07 16:53 ` [PATCH v5 0/3] completion of 'git [-C <dir>] diff' Elijah Newren
2026-08-12 16:25 ` Junio C Hamano [this message]
2026-08-12 16:25 ` [PATCH v6 1/3] completion: no-op refactoring of diff completion Junio C Hamano
2026-08-12 16:25 ` [PATCH v6 2/3] completion: complete tracked paths for 'git diff' Junio C Hamano
2026-08-12 16:25 ` [PATCH v6 3/3] completion: 'git diff' completes untracked paths as a last resort Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260812162551.2229680-1-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=ben.knoble@gmail.com \
--cc=britton.kerin@gmail.com \
--cc=git@vger.kernel.org \
--cc=levraiphilippeblain@gmail.com \
--cc=newren@gmail.com \
--cc=ps@pks.im \
--cc=rjusto@gmail.com \
--cc=szeder.dev@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox