Volume XXII, number 279Tuesday, October 6, 2026Latest message 17 minutes ago

The Git List

News and archive of git@vger.kernel.org, since April 2005

patch, 2 partscompletion of 'git [-C <dir>] checkout'

19 messages between Aug 11, 2026 and Aug 14, 2026, from Junio C Hamano, Ben Knoble, Elijah Newren.

Plain Markdown or JSON for tools and agents. Diffs are folded; open one to read it.

Junio C HamanoAug 11, 2026, 03:19 UTC on lore

Continuing from the previous 'git [-C <dir>] diff' series, these two patches correct completion for 'git checkout [-C <dir>] path<TAB>', but without falling back to untracked paths, as "checkout paths out of the index" is by definition about paths that appear in the index.

 1/2: completion: no-op refactoring of checkout completion
 2/2: completion: complete tracked paths for "git checkout"
 contrib/completion/git-completion.bash | 86 ++++++++++++++------------
 t/t9902-completion.sh                  | 27 ++++++++
 2 files changed, 73 insertions(+), 40 deletions(-)
Junio C HamanoAug 11, 2026, 03:21 UTC in reply to Junio C Hamano on lore

[PATCH 1/2] completion: no-op refactoring of checkout completion

The 'git checkout' completion function punts very early when it sees '--' on the command line, as it indicates that options or revisions can no longer appear. By returning early, it allows the default Bash action (which completes files in '$PWD') to kick in.

In preparation for changing what happens in the next step when option or revision completion yields no matching candidates, or when '--' is present, reorganize the control flow to avoid this early return, and add explicit returns to the option completion branches.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash | 84 +++++++++++++-------------
 1 file changed, 43 insertions(+), 41 deletions(-)
Show changes to contrib/completion/git-completion.bash +43 −41
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d35b4f3024..38dec1cabe 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1735,49 +1735,51 @@ __git_checkout_default_dwim_mode ()
 
 _git_checkout ()
 {
-	__git_has_doubledash && return
-
-	local dwim_opt="$(__git_checkout_default_dwim_mode)"
-
-	case "$prev" in
-	-b|-B|--orphan)
-		# Complete local branches (and DWIM branch
-		# remote branch names) for an option argument
-		# specifying a new branch name. This is for
-		# convenience, assuming new branches are
-		# possibly based on pre-existing branch names.
-		__git_complete_refs $dwim_opt --mode="heads"
-		return
-		;;
-	*)
-		;;
-	esac
+	if ! __git_has_doubledash; then
+		local dwim_opt="$(__git_checkout_default_dwim_mode)"
 
-	case "$cur" in
-	--conflict=*)
-		__gitcomp "diff3 merge zdiff3" "" "${cur##--conflict=}"
-		;;
-	--*)
-		__gitcomp_builtin checkout
-		;;
-	*)
-		# At this point, we've already handled special completion for
-		# the arguments to -b/-B, and --orphan. There are 3 main
-		# things left we can possibly complete:
-		# 1) a start-point for -b/-B, -d/--detach, or --orphan
-		# 2) a remote head, for --track
-		# 3) an arbitrary reference, possibly including DWIM names
-		#
+		case "$prev" in
+		-b|-B|--orphan)
+			# Complete local branches (and DWIM branch
+			# remote branch names) for an option argument
+			# specifying a new branch name. This is for
+			# convenience, assuming new branches are
+			# possibly based on pre-existing branch names.
+			__git_complete_refs $dwim_opt --mode="heads"
+			return
+			;;
+		*)
+			;;
+		esac
 
-		if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
-			__git_complete_refs --mode="refs"
-		elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
-			__git_complete_refs --mode="remote-heads"
-		else
-			__git_complete_refs $dwim_opt --mode="refs"
-		fi
-		;;
-	esac
+		case "$cur" in
+		--conflict=*)
+			__gitcomp "diff3 merge zdiff3" "" "${cur##--conflict=}"
+			return
+			;;
+		--*)
+			__gitcomp_builtin checkout
+			return
+			;;
+		*)
+			# At this point, we've already handled special completion for
+			# the arguments to -b/-B, and --orphan. There are 3 main
+			# things left we can possibly complete:
+			# 1) a start-point for -b/-B, -d/--detach, or --orphan
+			# 2) a remote head, for --track
+			# 3) an arbitrary reference, possibly including DWIM names
+			#
+
+			if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
+				__git_complete_refs --mode="refs"
+			elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
+				__git_complete_refs --mode="remote-heads"
+			else
+				__git_complete_refs $dwim_opt --mode="refs"
+			fi
+			;;
+		esac
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
-- 
2.55.0-698-g3e60a4dc4e
Junio C HamanoAug 11, 2026, 03:21 UTC in reply to Junio C Hamano on lore

[PATCH 2/2] completion: complete tracked paths for "git checkout"

When completing arguments for "git checkout", _git_checkout() delegates to __git_complete_refs(), which only completes revision references. This is good, as mixing revisions and paths in a single list from which the user can choose is confusing. However, if no reference matches, or if "--" is given, _git_checkout() leaves COMPREPLY empty. Bash then falls back to the default filename completion in $PWD.

This fails when "git -C <path>" is used, as $PWD is not the target repository.

Update _git_checkout() 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.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash |  4 ++++
 t/t9902-completion.sh                  | 27 ++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)
Show changes to 2 files +31 −0

contrib/completion/git-completion.bash, t/t9902-completion.sh

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 38dec1cabe..bd4b6e9247 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1780,6 +1780,10 @@ _git_checkout ()
 			;;
 		esac
 	fi
+
+	if [ ${#COMPREPLY[@]} -eq 0 ]; then
+		__git_complete_index_file
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 53a2bfb2ac..46fe94d8d5 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2713,6 +2713,33 @@ test_expect_success 'git -C <path> checkout uses the right repo' '
 	EOF
 '
 
+test_expect_success 'git checkout completes tracked paths when no refs match' '
+	# file1 and file2 are tracked but ufile is not
+	# there is no ref that begins with f
+	test_completion "git checkout f" <<-\EOF &&
+	file1
+	file2
+	EOF
+	test_completion "git checkout -- f" <<-\EOF
+	file1
+	file2
+	EOF
+'
+
+test_expect_success 'git -C <path> checkout completes tracked paths in specified repo' '
+	test_when_finished "rm -rf repo-for-checkout" &&
+	git init repo-for-checkout &&
+	echo content >repo-for-checkout/otherfile &&
+	git -C repo-for-checkout add otherfile &&
+	git -C repo-for-checkout commit -m otherfile &&
+	test_completion "git -C repo-for-checkout checkout o" <<-\EOF &&
+	otherfile
+	EOF
+	test_completion "git -C repo-for-checkout checkout -- o" <<-\EOF
+	otherfile
+	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
-- 
2.55.0-698-g3e60a4dc4e
Junio C HamanoAug 11, 2026, 04:04 UTC in reply to Junio C Hamano on lore

Re: [PATCH 0/2] completion of 'git [-C <dir>] checkout'

Junio C Hamano <gitster@pobox.com> writes:
> Continuing from the previous 'git [-C <dir>] diff' series, these two
> patches correct completion for 'git checkout [-C <dir>] path<TAB>',
> but without falling back to untracked paths, as "checkout paths out
> of the index" is by definition about paths that appear in the index.

I suppose I will add the 'untracked, too' final fallback, just like 'diff', because 'git checkout other-branch foo<TAB>' could resurrect a path like 'foolish' that appears on 'other-branch' but not in the currently checked-out branch (and thus not in the index). The 'foolish' file might also appear in the working tree as an untracked path.

This is not particularly useful, however, as it is unlikely that a file like 'foolish' tracked on another branch would be lying around untracked in the working tree to begin with.

I did not, however, find any readily usable machinery in the 'git-completion.bash' script that allows completing a path within an arbitrary tree. If such machinery were available, 'git checkout other-branch foo<TAB>' could capture the output of 'git ls-tree -r other-branch' and offer paths that begin with the given prefix.

Regardless, implementing this is beyond my 'git-completion-fu' right now. As I mentioned, I barely managed the 'diff' completion as a monkey-see-monkey-do patch series, and I would welcome others building on top of this once the dust settles.

Show 6 quoted lines
>  1/2: completion: no-op refactoring of checkout completion
>  2/2: completion: complete tracked paths for "git checkout"
>
>  contrib/completion/git-completion.bash | 86 ++++++++++++++------------
>  t/t9902-completion.sh                  | 27 ++++++++
>  2 files changed, 73 insertions(+), 40 deletions(-)
Ben KnobleAug 11, 2026, 16:32 UTC in reply to Junio C Hamano on lore

Re: [PATCH 2/2] completion: complete tracked paths for "git checkout"

Show 37 quoted lines
> 
> Le 10 août 2026 à 23:21, Junio C Hamano <gitster@pobox.com> a écrit :
> 
> When completing arguments for "git checkout", _git_checkout()
> delegates to __git_complete_refs(), which only completes revision
> references.  This is good, as mixing revisions and paths in a single
> list from which the user can choose is confusing.  However, if no
> reference matches, or if "--" is given, _git_checkout() leaves
> COMPREPLY empty.  Bash then falls back to the default filename
> completion in $PWD.
> 
> This fails when "git -C <path>" is used, as $PWD is not the target
> repository.
> 
> Update _git_checkout() 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.
> 
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
> contrib/completion/git-completion.bash |  4 ++++
> t/t9902-completion.sh                  | 27 ++++++++++++++++++++++++++
> 2 files changed, 31 insertions(+)
> 
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 38dec1cabe..bd4b6e9247 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1780,6 +1780,10 @@ _git_checkout ()
>            ;;
>        esac
>    fi
> +
> +    if [ ${#COMPREPLY[@]} -eq 0 ]; then
> +        __git_complete_index_file
> +    fi
> }
Assuming the prior step was purely mechanical, which I did not validate, this looks reasonable to me. 
Ben KnobleAug 11, 2026, 16:33 UTC in reply to Junio C Hamano on lore

Re: [PATCH 0/2] completion of 'git [-C <dir>] checkout'

Show 30 quoted lines
> Le 11 août 2026 à 00:04, Junio C Hamano <gitster@pobox.com> a écrit :
> 
> Junio C Hamano <gitster@pobox.com> writes:
> 
>> Continuing from the previous 'git [-C <dir>] diff' series, these two
>> patches correct completion for 'git checkout [-C <dir>] path<TAB>',
>> but without falling back to untracked paths, as "checkout paths out
>> of the index" is by definition about paths that appear in the index.
> 
> I suppose I will add the 'untracked, too' final fallback, just like
> 'diff', because 'git checkout other-branch foo<TAB>' could resurrect
> a path like 'foolish' that appears on 'other-branch' but not in the
> currently checked-out branch (and thus not in the index).  The
> 'foolish' file might also appear in the working tree as an untracked
> path.
> 
> This is not particularly useful, however, as it is unlikely that a
> file like 'foolish' tracked on another branch would be lying
> around untracked in the working tree to begin with.
> 
> I did not, however, find any readily usable machinery in the
> 'git-completion.bash' script that allows completing a path within an
> arbitrary tree.  If such machinery were available, 'git checkout
> other-branch foo<TAB>' could capture the output of 'git ls-tree -r
> other-branch' and offer paths that begin with the given prefix.
> 
> Regardless, implementing this is beyond my 'git-completion-fu' right
> now.  As I mentioned, I barely managed the 'diff' completion as a
> monkey-see-monkey-do patch series, and I would welcome others
> building on top of this once the dust settles.
I do not know where it lives (and it may be Zsh-specific) [partly because I haven’t looked while on mobile], but I think there is support for completing « path » in « git show <tree>:», so there might be something to build on there. 
Junio C HamanoAug 11, 2026, 17:25 UTC in reply to Ben Knoble on lore

Re: [PATCH 2/2] completion: complete tracked paths for "git checkout"

Ben Knoble <ben.knoble@gmail.com> writes:
Show 39 quoted lines
>> 
>> Le 10 août 2026 à 23:21, Junio C Hamano <gitster@pobox.com> a écrit :
>> 
>> When completing arguments for "git checkout", _git_checkout()
>> delegates to __git_complete_refs(), which only completes revision
>> references.  This is good, as mixing revisions and paths in a single
>> list from which the user can choose is confusing.  However, if no
>> reference matches, or if "--" is given, _git_checkout() leaves
>> COMPREPLY empty.  Bash then falls back to the default filename
>> completion in $PWD.
>> 
>> This fails when "git -C <path>" is used, as $PWD is not the target
>> repository.
>> 
>> Update _git_checkout() 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.
>> 
>> Signed-off-by: Junio C Hamano <gitster@pobox.com>
>> ---
>> contrib/completion/git-completion.bash |  4 ++++
>> t/t9902-completion.sh                  | 27 ++++++++++++++++++++++++++
>> 2 files changed, 31 insertions(+)
>> 
>> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
>> index 38dec1cabe..bd4b6e9247 100644
>> --- a/contrib/completion/git-completion.bash
>> +++ b/contrib/completion/git-completion.bash
>> @@ -1780,6 +1780,10 @@ _git_checkout ()
>>            ;;
>>        esac
>>    fi
>> +
>> +    if [ ${#COMPREPLY[@]} -eq 0 ]; then
>> +        __git_complete_index_file
>> +    fi
>> }
>
> Assuming the prior step was purely mechanical, which I did not validate, this looks reasonable to me. 

Actually the new call should use "--cached" to complete from the paths in the index, I think.

Junio C HamanoAug 12, 2026, 01:45 UTC in reply to Ben Knoble on lore

Re: [PATCH 0/2] completion of 'git [-C <dir>] checkout'

Ben Knoble <ben.knoble@gmail.com> writes:
Show 17 quoted lines
>> Le 11 août 2026 à 00:04, Junio C Hamano <gitster@pobox.com> a écrit :
>> 
>> I did not, however, find any readily usable machinery in the
>> 'git-completion.bash' script that allows completing a path within an
>> arbitrary tree.  If such machinery were available, 'git checkout
>> other-branch foo<TAB>' could capture the output of 'git ls-tree -r
>> other-branch' and offer paths that begin with the given prefix.
>> 
>> Regardless, implementing this is beyond my 'git-completion-fu' right
>> now.  As I mentioned, I barely managed the 'diff' completion as a
>> monkey-see-monkey-do patch series, and I would welcome others
>> building on top of this once the dust settles.
>
> I do not know where it lives (and it may be Zsh-specific) [partly
> because I haven’t looked while on mobile], but I think there is
> support for completing « path » in « git show <tree>:», so there
> might be something to build on there.

I know where treeish:path<TAB> support is. The thing is, it is not a reusable machinery for "git checkout treeish path<TAB>".

Thanks.
Junio C HamanoAug 12, 2026, 16:48 UTC in reply to Junio C Hamano on lore

[PATCH v2 0/3] completion of 'git [-C <dir>] checkout'

Continuing from the previous 'git [-C <dir>] diff' series, these two patches correct completion for 'git checkout [-C <dir>] path<TAB>', but without falling back to untracked paths, as "checkout paths out of the index" is by definition about paths that appear in the index.

This has been rebuilt on the v6 iteration of the 'complete-diff' topic to give the tests a more structured and logical organization.

Additionally, [PATCH 3/3] is new. It teaches the completion machinery to complete untracked paths in the working tree, which may be of limited use, as it is unlikely that a file tracked on another branch (and thus capable of being restored with 'git checkout another-branch path') would be lying around untracked in the working tree to begin with.

 1/3: completion: no-op refactoring of checkout completion
 2/3: completion: complete tracked paths for "git checkout"
 3/3: completion: 'git checkout' completes untracked paths as a last
        resort
 contrib/completion/git-completion.bash | 88 ++++++++++++++------------
 t/t9902-completion.sh                  | 56 ++++++++++++++++
 2 files changed, 105 insertions(+), 39 deletions(-)
Range-diff against v1:
1:  f35017f5c9 = 1:  d3b022ac73 completion: no-op refactoring of checkout completion
2:  20d57f0336 ! 2:  85019fbf97 completion: complete tracked paths for "git checkout"
    @@ contrib/completion/git-completion.bash: _git_checkout ()
      	fi
     +
     +	if [ ${#COMPREPLY[@]} -eq 0 ]; then
    -+		__git_complete_index_file
    ++		__git_complete_index_file ""
     +	fi
      }
      
    @@ t/t9902-completion.sh: test_expect_success 'git -C <path> checkout uses the righ
      '
      
     +test_expect_success 'git checkout completes tracked paths when no refs match' '
    -+	# file1 and file2 are tracked but ufile is not
    ++	# file1 and file2 are tracked but file3 is not
     +	# there is no ref that begins with f
     +	test_completion "git checkout f" <<-\EOF &&
     +	file1
    @@ t/t9902-completion.sh: test_expect_success 'git -C <path> checkout uses the righ
     +	EOF
     +'
     +
    -+test_expect_success 'git -C <path> checkout completes tracked paths in specified repo' '
    ++test_expect_success 'git -C <path> checkout completes paths in specified repo' '
    ++	# otherfile is tracked, oops is not
    ++	# lostfile is tracked but lost
     +	test_when_finished "rm -rf repo-for-checkout" &&
     +	git init repo-for-checkout &&
     +	echo content >repo-for-checkout/otherfile &&
    ++	echo content >repo-for-checkout/lostfile &&
     +	git -C repo-for-checkout add otherfile &&
    ++	git -C repo-for-checkout add lostfile &&
     +	git -C repo-for-checkout commit -m otherfile &&
    ++	echo untracked >repo-for-checkout/oops &&
    ++	rm -f repo-for-checkout/lostfile &&
     +	test_completion "git -C repo-for-checkout checkout o" <<-\EOF &&
     +	otherfile
     +	EOF
    -+	test_completion "git -C repo-for-checkout checkout -- o" <<-\EOF
    ++	test_completion "git -C repo-for-checkout checkout -- o" <<-\EOF &&
     +	otherfile
     +	EOF
    ++	test_completion "git -C repo-for-checkout checkout l" <<-\EOF &&
    ++	lostfile
    ++	EOF
    ++	test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF
    ++	lostfile
    ++	EOF
     +'
     +
      test_expect_success 'git diff completes tracked paths when no refs match' '
-:  ---------- > 3:  56aade8759 completion: 'git checkout' completes untracked paths as a last resort
Junio C HamanoAug 12, 2026, 16:48 UTC in reply to Junio C Hamano on lore

[PATCH v2 1/3] completion: no-op refactoring of checkout completion

The 'git checkout' completion function punts very early when it sees '--' on the command line, as it indicates that options or revisions can no longer appear. By returning early, it allows the default Bash action (which completes files in '$PWD') to kick in.

In preparation for changing what happens in the next step when option or revision completion yields no matching candidates, or when '--' is present, reorganize the control flow to avoid this early return, and add explicit returns to the option completion branches.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash | 84 +++++++++++++-------------
 1 file changed, 43 insertions(+), 41 deletions(-)
Show changes to contrib/completion/git-completion.bash +43 −41
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d35b4f3024..38dec1cabe 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1735,49 +1735,51 @@ __git_checkout_default_dwim_mode ()
 
 _git_checkout ()
 {
-	__git_has_doubledash && return
-
-	local dwim_opt="$(__git_checkout_default_dwim_mode)"
-
-	case "$prev" in
-	-b|-B|--orphan)
-		# Complete local branches (and DWIM branch
-		# remote branch names) for an option argument
-		# specifying a new branch name. This is for
-		# convenience, assuming new branches are
-		# possibly based on pre-existing branch names.
-		__git_complete_refs $dwim_opt --mode="heads"
-		return
-		;;
-	*)
-		;;
-	esac
+	if ! __git_has_doubledash; then
+		local dwim_opt="$(__git_checkout_default_dwim_mode)"
 
-	case "$cur" in
-	--conflict=*)
-		__gitcomp "diff3 merge zdiff3" "" "${cur##--conflict=}"
-		;;
-	--*)
-		__gitcomp_builtin checkout
-		;;
-	*)
-		# At this point, we've already handled special completion for
-		# the arguments to -b/-B, and --orphan. There are 3 main
-		# things left we can possibly complete:
-		# 1) a start-point for -b/-B, -d/--detach, or --orphan
-		# 2) a remote head, for --track
-		# 3) an arbitrary reference, possibly including DWIM names
-		#
+		case "$prev" in
+		-b|-B|--orphan)
+			# Complete local branches (and DWIM branch
+			# remote branch names) for an option argument
+			# specifying a new branch name. This is for
+			# convenience, assuming new branches are
+			# possibly based on pre-existing branch names.
+			__git_complete_refs $dwim_opt --mode="heads"
+			return
+			;;
+		*)
+			;;
+		esac
 
-		if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
-			__git_complete_refs --mode="refs"
-		elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
-			__git_complete_refs --mode="remote-heads"
-		else
-			__git_complete_refs $dwim_opt --mode="refs"
-		fi
-		;;
-	esac
+		case "$cur" in
+		--conflict=*)
+			__gitcomp "diff3 merge zdiff3" "" "${cur##--conflict=}"
+			return
+			;;
+		--*)
+			__gitcomp_builtin checkout
+			return
+			;;
+		*)
+			# At this point, we've already handled special completion for
+			# the arguments to -b/-B, and --orphan. There are 3 main
+			# things left we can possibly complete:
+			# 1) a start-point for -b/-B, -d/--detach, or --orphan
+			# 2) a remote head, for --track
+			# 3) an arbitrary reference, possibly including DWIM names
+			#
+
+			if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
+				__git_complete_refs --mode="refs"
+			elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
+				__git_complete_refs --mode="remote-heads"
+			else
+				__git_complete_refs $dwim_opt --mode="refs"
+			fi
+			;;
+		esac
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
-- 
2.55.0-721-g26b8014fc4
Junio C HamanoAug 12, 2026, 16:48 UTC in reply to Junio C Hamano on lore

[PATCH v2 2/3] completion: complete tracked paths for "git checkout"

When completing arguments for "git checkout", _git_checkout() delegates to __git_complete_refs(), which only completes revision references. This is good, as mixing revisions and paths in a single list from which the user can choose is confusing. However, if no reference matches, or if "--" is given, _git_checkout() leaves COMPREPLY empty. Bash then falls back to the default filename completion in $PWD.

This fails when "git -C <path>" is used, as $PWD is not the target repository.

Update _git_checkout() 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.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash |  4 +++
 t/t9902-completion.sh                  | 39 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
Show changes to 2 files +43 −0

contrib/completion/git-completion.bash, t/t9902-completion.sh

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 38dec1cabe..0eecfcbf8b 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1780,6 +1780,10 @@ _git_checkout ()
 			;;
 		esac
 	fi
+
+	if [ ${#COMPREPLY[@]} -eq 0 ]; then
+		__git_complete_index_file ""
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index b889ec8c77..13fa5c65c3 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2714,6 +2714,45 @@ test_expect_success 'git -C <path> checkout uses the right repo' '
 	EOF
 '
 
+test_expect_success 'git checkout completes tracked paths when no refs match' '
+	# file1 and file2 are tracked but file3 is not
+	# there is no ref that begins with f
+	test_completion "git checkout f" <<-\EOF &&
+	file1
+	file2
+	EOF
+	test_completion "git checkout -- f" <<-\EOF
+	file1
+	file2
+	EOF
+'
+
+test_expect_success 'git -C <path> checkout completes paths in specified repo' '
+	# otherfile is tracked, oops is not
+	# lostfile is tracked but lost
+	test_when_finished "rm -rf repo-for-checkout" &&
+	git init repo-for-checkout &&
+	echo content >repo-for-checkout/otherfile &&
+	echo content >repo-for-checkout/lostfile &&
+	git -C repo-for-checkout add otherfile &&
+	git -C repo-for-checkout add lostfile &&
+	git -C repo-for-checkout commit -m otherfile &&
+	echo untracked >repo-for-checkout/oops &&
+	rm -f repo-for-checkout/lostfile &&
+	test_completion "git -C repo-for-checkout checkout o" <<-\EOF &&
+	otherfile
+	EOF
+	test_completion "git -C repo-for-checkout checkout -- o" <<-\EOF &&
+	otherfile
+	EOF
+	test_completion "git -C repo-for-checkout checkout l" <<-\EOF &&
+	lostfile
+	EOF
+	test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF
+	lostfile
+	EOF
+'
+
 test_expect_success 'git diff completes tracked paths when no refs match' '
 	# file1 and file2 are tracked but file3 is not
 	# there is no ref that begins with f
-- 
2.55.0-721-g26b8014fc4
Junio C HamanoAug 12, 2026, 16:48 UTC in reply to Junio C Hamano on lore

[PATCH v2 3/3] completion: 'git checkout' completes untracked paths as a last resort

We taught 'git checkout' to first try to complete revisions (unless '--' is present on the command line) and, failing that, to complete tracked paths. If this yields nothing, it lets the Bash default, which offers paths in $PWD, kick in.

Teach it to complete untracked paths before giving up and letting the Bash default kick in. With this change,

    $ git -C another-directory checkout un<TAB>

finds the 'untracked' file in another-directory and offers it as a completion candidate.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash |  4 ++++
 t/t9902-completion.sh                  | 21 +++++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)
Show changes to 2 files +23 −2

contrib/completion/git-completion.bash, t/t9902-completion.sh

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0eecfcbf8b..22c53697ab 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1784,6 +1784,10 @@ _git_checkout ()
 	if [ ${#COMPREPLY[@]} -eq 0 ]; then
 		__git_complete_index_file ""
 	fi
+
+	if [ ${#COMPREPLY[@]} -eq 0 ]; then
+		__git_complete_index_file "--others"
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 13fa5c65c3..e8418f069b 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2727,9 +2727,19 @@ test_expect_success 'git checkout completes tracked paths when no refs match' '
 	EOF
 '
 
+test_expect_success 'git checkout completes untracked paths, too' '
+	# ufile is not tracked and there is no ref that begins with u
+	test_completion "git checkout u" <<-\EOF &&
+	ufile
+	EOF
+	test_completion "git checkout -- u" <<-\EOF
+	ufile
+	EOF
+'
+
 test_expect_success 'git -C <path> checkout completes paths in specified repo' '
 	# otherfile is tracked, oops is not
-	# lostfile is tracked but lost
+	# lostfile is tracked but lost, ufile is untracked.
 	test_when_finished "rm -rf repo-for-checkout" &&
 	git init repo-for-checkout &&
 	echo content >repo-for-checkout/otherfile &&
@@ -2738,6 +2748,7 @@ test_expect_success 'git -C <path> checkout completes paths in specified repo' '
 	git -C repo-for-checkout add lostfile &&
 	git -C repo-for-checkout commit -m otherfile &&
 	echo untracked >repo-for-checkout/oops &&
+	echo untracked >repo-for-checkout/ufile &&
 	rm -f repo-for-checkout/lostfile &&
 	test_completion "git -C repo-for-checkout checkout o" <<-\EOF &&
 	otherfile
@@ -2748,9 +2759,15 @@ test_expect_success 'git -C <path> checkout completes paths in specified repo' '
 	test_completion "git -C repo-for-checkout checkout l" <<-\EOF &&
 	lostfile
 	EOF
-	test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF
+	test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF &&
 	lostfile
 	EOF
+	test_completion "git -C repo-for-checkout checkout u" <<-\EOF &&
+	ufile
+	EOF
+	test_completion "git -C repo-for-checkout checkout -- u" <<-\EOF
+	ufile
+	EOF
 '
 
 test_expect_success 'git diff completes tracked paths when no refs match' '
-- 
2.55.0-721-g26b8014fc4
Elijah NewrenAug 12, 2026, 19:57 UTC in reply to Junio C Hamano on lore

Re: [PATCH v2 3/3] completion: 'git checkout' completes untracked paths as a last resort

On Wed, Aug 12, 2026 at 9:49 AM Junio C Hamano <gitster@pobox.com> wrote:
Show 32 quoted lines
>
> We taught 'git checkout' to first try to complete revisions (unless
> '--' is present on the command line) and, failing that, to complete
> tracked paths.  If this yields nothing, it lets the Bash default,
> which offers paths in $PWD, kick in.
>
> Teach it to complete untracked paths before giving up and letting
> the Bash default kick in.  With this change,
>
>     $ git -C another-directory checkout un<TAB>
>
> finds the 'untracked' file in another-directory and offers it as a
> completion candidate.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  contrib/completion/git-completion.bash |  4 ++++
>  t/t9902-completion.sh                  | 21 +++++++++++++++++++--
>  2 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 0eecfcbf8b..22c53697ab 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1784,6 +1784,10 @@ _git_checkout ()
>         if [ ${#COMPREPLY[@]} -eq 0 ]; then
>                 __git_complete_index_file ""
>         fi
> +
> +       if [ ${#COMPREPLY[@]} -eq 0 ]; then
> +               __git_complete_index_file "--others"
> +       fi

In your completion series for `git diff`, you passed "--others --directory", but you omit --directory here.

I think playing around with it for a while that it works either way, because without --directory __git_index_files splits on "/" and only keeps the leading component, but not passing --directory means it'll just have to parse through and then compress more options.

It's probably not a big deal either way, but might be nice to include "--directory" here for consistency with your diff series, and because it'll be a bit more performant.

Show 54 quoted lines
>  }
>
>  __git_sequencer_inprogress_options="--continue --quit --abort --skip"
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index 13fa5c65c3..e8418f069b 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2727,9 +2727,19 @@ test_expect_success 'git checkout completes tracked paths when no refs match' '
>         EOF
>  '
>
> +test_expect_success 'git checkout completes untracked paths, too' '
> +       # ufile is not tracked and there is no ref that begins with u
> +       test_completion "git checkout u" <<-\EOF &&
> +       ufile
> +       EOF
> +       test_completion "git checkout -- u" <<-\EOF
> +       ufile
> +       EOF
> +'
> +
>  test_expect_success 'git -C <path> checkout completes paths in specified repo' '
>         # otherfile is tracked, oops is not
> -       # lostfile is tracked but lost
> +       # lostfile is tracked but lost, ufile is untracked.
>         test_when_finished "rm -rf repo-for-checkout" &&
>         git init repo-for-checkout &&
>         echo content >repo-for-checkout/otherfile &&
> @@ -2738,6 +2748,7 @@ test_expect_success 'git -C <path> checkout completes paths in specified repo' '
>         git -C repo-for-checkout add lostfile &&
>         git -C repo-for-checkout commit -m otherfile &&
>         echo untracked >repo-for-checkout/oops &&
> +       echo untracked >repo-for-checkout/ufile &&
>         rm -f repo-for-checkout/lostfile &&
>         test_completion "git -C repo-for-checkout checkout o" <<-\EOF &&
>         otherfile
> @@ -2748,9 +2759,15 @@ test_expect_success 'git -C <path> checkout completes paths in specified repo' '
>         test_completion "git -C repo-for-checkout checkout l" <<-\EOF &&
>         lostfile
>         EOF
> -       test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF
> +       test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF &&
>         lostfile
>         EOF
> +       test_completion "git -C repo-for-checkout checkout u" <<-\EOF &&
> +       ufile
> +       EOF
> +       test_completion "git -C repo-for-checkout checkout -- u" <<-\EOF
> +       ufile
> +       EOF
>  '
>
>  test_expect_success 'git diff completes tracked paths when no refs match' '
> --
Looks fine otherwise (as do the first two patches).
Junio C HamanoAug 12, 2026, 20:18 UTC in reply to Elijah Newren on lore

Re: [PATCH v2 3/3] completion: 'git checkout' completes untracked paths as a last resort

Elijah Newren <newren@gmail.com> writes:
> It's probably not a big deal either way, but might be nice to include
> "--directory" here for consistency with your diff series, and because
> it'll be a bit more performant.
Thanks, will do.
Junio C HamanoAug 13, 2026, 19:12 UTC in reply to Junio C Hamano on lore

[PATCH v3 0/3] completion of 'git [-C <dir>] checkout'

Continuing from the previous 'git [-C <dir>] diff' series, these patches correct completion for 'git checkout [-C <dir>] path<TAB>', with a fallback to complete untracked paths of somewhat dubious value, primarily as a reminder for future work.

Hopefully this will be the small and final update to the series.
 1/3: completion: no-op refactoring of checkout completion
 2/3: completion: complete tracked paths for "git checkout"
 3/3: completion: 'git checkout' completes untracked paths as a last
        resort
 contrib/completion/git-completion.bash | 88 ++++++++++++++------------
 t/t9902-completion.sh                  | 56 ++++++++++++++++
 2 files changed, 105 insertions(+), 39 deletions(-)
Range-diff against v2:
1:  33d136ffde = 1:  33d136ffde completion: no-op refactoring of checkout completion
2:  a28754cfd9 = 2:  a28754cfd9 completion: complete tracked paths for "git checkout"
3:  90aec6539c ! 3:  17880068c0 completion: 'git checkout' completes untracked paths as a last resort
    @@ contrib/completion/git-completion.bash: _git_checkout ()
      	fi
     +
     +	if [ ${#COMPREPLY[@]} -eq 0 ]; then
    -+		__git_complete_index_file "--others"
    ++		__git_complete_index_file "--others --directory"
     +	fi
      }
      
-- 
2.55.0-759-g9dcc51a0fd
Junio C HamanoAug 13, 2026, 19:12 UTC in reply to Junio C Hamano on lore

[PATCH v3 1/3] completion: no-op refactoring of checkout completion

The 'git checkout' completion function punts very early when it sees '--' on the command line, as it indicates that options or revisions can no longer appear. By returning early, it allows the default Bash action (which completes files in '$PWD') to kick in.

In preparation for changing what happens in the next step when option or revision completion yields no matching candidates, or when '--' is present, reorganize the control flow to avoid this early return, and add explicit returns to the option completion branches.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash | 84 +++++++++++++-------------
 1 file changed, 43 insertions(+), 41 deletions(-)
Show changes to contrib/completion/git-completion.bash +43 −41
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d35b4f3024..38dec1cabe 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1735,49 +1735,51 @@ __git_checkout_default_dwim_mode ()
 
 _git_checkout ()
 {
-	__git_has_doubledash && return
-
-	local dwim_opt="$(__git_checkout_default_dwim_mode)"
-
-	case "$prev" in
-	-b|-B|--orphan)
-		# Complete local branches (and DWIM branch
-		# remote branch names) for an option argument
-		# specifying a new branch name. This is for
-		# convenience, assuming new branches are
-		# possibly based on pre-existing branch names.
-		__git_complete_refs $dwim_opt --mode="heads"
-		return
-		;;
-	*)
-		;;
-	esac
+	if ! __git_has_doubledash; then
+		local dwim_opt="$(__git_checkout_default_dwim_mode)"
 
-	case "$cur" in
-	--conflict=*)
-		__gitcomp "diff3 merge zdiff3" "" "${cur##--conflict=}"
-		;;
-	--*)
-		__gitcomp_builtin checkout
-		;;
-	*)
-		# At this point, we've already handled special completion for
-		# the arguments to -b/-B, and --orphan. There are 3 main
-		# things left we can possibly complete:
-		# 1) a start-point for -b/-B, -d/--detach, or --orphan
-		# 2) a remote head, for --track
-		# 3) an arbitrary reference, possibly including DWIM names
-		#
+		case "$prev" in
+		-b|-B|--orphan)
+			# Complete local branches (and DWIM branch
+			# remote branch names) for an option argument
+			# specifying a new branch name. This is for
+			# convenience, assuming new branches are
+			# possibly based on pre-existing branch names.
+			__git_complete_refs $dwim_opt --mode="heads"
+			return
+			;;
+		*)
+			;;
+		esac
 
-		if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
-			__git_complete_refs --mode="refs"
-		elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
-			__git_complete_refs --mode="remote-heads"
-		else
-			__git_complete_refs $dwim_opt --mode="refs"
-		fi
-		;;
-	esac
+		case "$cur" in
+		--conflict=*)
+			__gitcomp "diff3 merge zdiff3" "" "${cur##--conflict=}"
+			return
+			;;
+		--*)
+			__gitcomp_builtin checkout
+			return
+			;;
+		*)
+			# At this point, we've already handled special completion for
+			# the arguments to -b/-B, and --orphan. There are 3 main
+			# things left we can possibly complete:
+			# 1) a start-point for -b/-B, -d/--detach, or --orphan
+			# 2) a remote head, for --track
+			# 3) an arbitrary reference, possibly including DWIM names
+			#
+
+			if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
+				__git_complete_refs --mode="refs"
+			elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
+				__git_complete_refs --mode="remote-heads"
+			else
+				__git_complete_refs $dwim_opt --mode="refs"
+			fi
+			;;
+		esac
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
-- 
2.55.0-759-g9dcc51a0fd
Junio C HamanoAug 13, 2026, 19:12 UTC in reply to Junio C Hamano on lore

[PATCH v3 2/3] completion: complete tracked paths for "git checkout"

When completing arguments for "git checkout", _git_checkout() delegates to __git_complete_refs(), which only completes revision references. This is good, as mixing revisions and paths in a single list from which the user can choose is confusing. However, if no reference matches, or if "--" is given, _git_checkout() leaves COMPREPLY empty. Bash then falls back to the default filename completion in $PWD.

This fails when "git -C <path>" is used, as $PWD is not the target repository.

Update _git_checkout() 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.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash |  4 +++
 t/t9902-completion.sh                  | 39 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
Show changes to 2 files +43 −0

contrib/completion/git-completion.bash, t/t9902-completion.sh

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 38dec1cabe..0eecfcbf8b 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1780,6 +1780,10 @@ _git_checkout ()
 			;;
 		esac
 	fi
+
+	if [ ${#COMPREPLY[@]} -eq 0 ]; then
+		__git_complete_index_file ""
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index b889ec8c77..13fa5c65c3 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2714,6 +2714,45 @@ test_expect_success 'git -C <path> checkout uses the right repo' '
 	EOF
 '
 
+test_expect_success 'git checkout completes tracked paths when no refs match' '
+	# file1 and file2 are tracked but file3 is not
+	# there is no ref that begins with f
+	test_completion "git checkout f" <<-\EOF &&
+	file1
+	file2
+	EOF
+	test_completion "git checkout -- f" <<-\EOF
+	file1
+	file2
+	EOF
+'
+
+test_expect_success 'git -C <path> checkout completes paths in specified repo' '
+	# otherfile is tracked, oops is not
+	# lostfile is tracked but lost
+	test_when_finished "rm -rf repo-for-checkout" &&
+	git init repo-for-checkout &&
+	echo content >repo-for-checkout/otherfile &&
+	echo content >repo-for-checkout/lostfile &&
+	git -C repo-for-checkout add otherfile &&
+	git -C repo-for-checkout add lostfile &&
+	git -C repo-for-checkout commit -m otherfile &&
+	echo untracked >repo-for-checkout/oops &&
+	rm -f repo-for-checkout/lostfile &&
+	test_completion "git -C repo-for-checkout checkout o" <<-\EOF &&
+	otherfile
+	EOF
+	test_completion "git -C repo-for-checkout checkout -- o" <<-\EOF &&
+	otherfile
+	EOF
+	test_completion "git -C repo-for-checkout checkout l" <<-\EOF &&
+	lostfile
+	EOF
+	test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF
+	lostfile
+	EOF
+'
+
 test_expect_success 'git diff completes tracked paths when no refs match' '
 	# file1 and file2 are tracked but file3 is not
 	# there is no ref that begins with f
-- 
2.55.0-759-g9dcc51a0fd
Junio C HamanoAug 13, 2026, 19:12 UTC in reply to Junio C Hamano on lore

[PATCH v3 3/3] completion: 'git checkout' completes untracked paths as a last resort

We taught 'git checkout' to first try to complete revisions (unless '--' is present on the command line) and, failing that, to complete tracked paths. If this yields nothing, it lets the Bash default, which offers paths in $PWD, kick in.

Teach it to complete untracked paths before giving up and letting the Bash default kick in. With this change,

    $ git -C another-directory checkout un<TAB>

finds the 'untracked' file in another-directory and offers it as a completion candidate.

Note that this is of somewhat dubious value, as an untracked path by definition does not exist in the index, so checking it out from the index would not work well. Even when used to check out the path from a different branch, it is still of dubious value because it is unlikely that a path tracked in another branch is lying untracked in the working tree, as switching from a branch with the path to a branch without it will normally remove the file in the working tree.

A better behavior probably is to detect the tree-ish argument on the command line and offer paths with the given prefix as candidates, but there is no __git_complete_from_tree() helper readily usable, so mark this as #leftoverbits to wait for another day.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 contrib/completion/git-completion.bash |  4 ++++
 t/t9902-completion.sh                  | 21 +++++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)
Show changes to 2 files +23 −2

contrib/completion/git-completion.bash, t/t9902-completion.sh

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0eecfcbf8b..e6dce62d3c 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1784,6 +1784,10 @@ _git_checkout ()
 	if [ ${#COMPREPLY[@]} -eq 0 ]; then
 		__git_complete_index_file ""
 	fi
+
+	if [ ${#COMPREPLY[@]} -eq 0 ]; then
+		__git_complete_index_file "--others --directory"
+	fi
 }
 
 __git_sequencer_inprogress_options="--continue --quit --abort --skip"
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 13fa5c65c3..e8418f069b 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2727,9 +2727,19 @@ test_expect_success 'git checkout completes tracked paths when no refs match' '
 	EOF
 '
 
+test_expect_success 'git checkout completes untracked paths, too' '
+	# ufile is not tracked and there is no ref that begins with u
+	test_completion "git checkout u" <<-\EOF &&
+	ufile
+	EOF
+	test_completion "git checkout -- u" <<-\EOF
+	ufile
+	EOF
+'
+
 test_expect_success 'git -C <path> checkout completes paths in specified repo' '
 	# otherfile is tracked, oops is not
-	# lostfile is tracked but lost
+	# lostfile is tracked but lost, ufile is untracked.
 	test_when_finished "rm -rf repo-for-checkout" &&
 	git init repo-for-checkout &&
 	echo content >repo-for-checkout/otherfile &&
@@ -2738,6 +2748,7 @@ test_expect_success 'git -C <path> checkout completes paths in specified repo' '
 	git -C repo-for-checkout add lostfile &&
 	git -C repo-for-checkout commit -m otherfile &&
 	echo untracked >repo-for-checkout/oops &&
+	echo untracked >repo-for-checkout/ufile &&
 	rm -f repo-for-checkout/lostfile &&
 	test_completion "git -C repo-for-checkout checkout o" <<-\EOF &&
 	otherfile
@@ -2748,9 +2759,15 @@ test_expect_success 'git -C <path> checkout completes paths in specified repo' '
 	test_completion "git -C repo-for-checkout checkout l" <<-\EOF &&
 	lostfile
 	EOF
-	test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF
+	test_completion "git -C repo-for-checkout checkout -- l" <<-\EOF &&
 	lostfile
 	EOF
+	test_completion "git -C repo-for-checkout checkout u" <<-\EOF &&
+	ufile
+	EOF
+	test_completion "git -C repo-for-checkout checkout -- u" <<-\EOF
+	ufile
+	EOF
 '
 
 test_expect_success 'git diff completes tracked paths when no refs match' '
-- 
2.55.0-759-g9dcc51a0fd
Elijah NewrenAug 14, 2026, 01:53 UTC in reply to Junio C Hamano on lore

Re: [PATCH v3 0/3] completion of 'git [-C <dir>] checkout'

On Thu, Aug 13, 2026 at 12:12 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 32 quoted lines
>
> Continuing from the previous 'git [-C <dir>] diff' series, these
> patches correct completion for 'git checkout [-C <dir>] path<TAB>',
> with a fallback to complete untracked paths of somewhat dubious
> value, primarily as a reminder for future work.
>
> Hopefully this will be the small and final update to the series.
>
>  1/3: completion: no-op refactoring of checkout completion
>  2/3: completion: complete tracked paths for "git checkout"
>  3/3: completion: 'git checkout' completes untracked paths as a last
>         resort
>
>  contrib/completion/git-completion.bash | 88 ++++++++++++++------------
>  t/t9902-completion.sh                  | 56 ++++++++++++++++
>  2 files changed, 105 insertions(+), 39 deletions(-)
>
> Range-diff against v2:
> 1:  33d136ffde = 1:  33d136ffde completion: no-op refactoring of checkout completion
> 2:  a28754cfd9 = 2:  a28754cfd9 completion: complete tracked paths for "git checkout"
> 3:  90aec6539c ! 3:  17880068c0 completion: 'git checkout' completes untracked paths as a last resort
>     @@ contrib/completion/git-completion.bash: _git_checkout ()
>         fi
>      +
>      +  if [ ${#COMPREPLY[@]} -eq 0 ]; then
>     -+          __git_complete_index_file "--others"
>     ++          __git_complete_index_file "--others --directory"
>      +  fi
>       }
>
> --
> 2.55.0-759-g9dcc51a0fd
This version looks good to me; thanks!

Back to recent threads