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>
Subject: [PATCH] completion: complete tracked paths for 'git diff'
Date: Sun, 02 Aug 2026 17:58:01 -0700 [thread overview]
Message-ID: <xmqqcxw010me.fsf@gitster.g> (raw)
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.
[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. The contribution
by any of them looked more expertly done by whatever I did here.
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
next reply other threads:[~2026-08-03 0:58 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-03 0:58 Junio C Hamano [this message]
2026-08-03 1:07 ` [PATCH] completion: complete tracked paths for 'git diff' 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
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=xmqqcxw010me.fsf@gitster.g \
--to=gitster@pobox.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 \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.