All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] worktree add: improve message for ambiguous remote branch name
@ 2026-08-08  8:21 Yoichi NAKAYAMA via GitGitGadget
  2026-08-08 17:00 ` Junio C Hamano
                   ` (4 more replies)
  0 siblings, 5 replies; 18+ messages in thread
From: Yoichi NAKAYAMA via GitGitGadget @ 2026-08-08  8:21 UTC (permalink / raw)
  To: git; +Cc: Yoichi NAKAYAMA, Yoichi NAKAYAMA

From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>

Display a descriptive message when DWIM fails.

Add advice on how to work around this by specifying the fully
qualified name or by setting checkout.defaultRemote.

Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
---
    worktree add: improve message for ambiguous remote branch name

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2197%2Fyoichi%2Fimprove-worktree-add-error-message-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2197/yoichi/improve-worktree-add-error-message-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2197

 builtin/worktree.c      | 30 ++++++++++++++++++++++++++----
 t/t2400-worktree-add.sh | 21 +++++++++++++++++++--
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 654d27c3e1..46bc305116 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -116,6 +116,16 @@ static const char * const git_worktree_unlock_usage[] = {
 	NULL
 };
 
+static const char message_advice_ambiguous_remote_tracking_branch[] =
+	N_("If you meant to create a worktree from a remote tracking branch on,\n"
+	   "e.g. 'origin', you can do so by fully qualifying the name:\n"
+	   "\n"
+	   "    git worktree add <path> origin/<name>\n"
+	   "\n"
+	   "If you'd like to always have checkouts of an ambiguous <name> prefer\n"
+	   "one remote, e.g. the 'origin' remote, consider setting\n"
+	   "checkout.defaultRemote=origin in your config.");
+
 struct add_opts {
 	int force;
 	int detach;
@@ -764,7 +774,7 @@ static int dwim_orphan(const struct add_opts *opts, int opt_track, int remote)
 	return 1;
 }
 
-static char *dwim_branch(const char *path, char **new_branch)
+static char *dwim_branch(const struct add_opts *opts, const char *path, char **new_branch)
 {
 	int n;
 	int branch_exists;
@@ -781,8 +791,14 @@ static char *dwim_branch(const char *path, char **new_branch)
 
 	*new_branch = branchname;
 	if (guess_remote) {
+		int num_matches = 0;
 		struct object_id oid;
-		char *remote = unique_tracking_name(*new_branch, &oid, NULL);
+		char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
+		if (!opts->quiet && !remote && num_matches > 1) {
+			if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
+				advise(_(message_advice_ambiguous_remote_tracking_branch));
+			warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
+		}
 		return remote;
 	}
 	return NULL;
@@ -890,7 +906,7 @@ static int add(int ac, const char **av, const char *prefix,
 		opts.orphan = dwim_orphan(&opts, !!opt_track, 0);
 	} else if (ac < 2) {
 		/* DWIM: Guess branch name from path. */
-		char *s = dwim_branch(path, &new_branch_to_free);
+		char *s = dwim_branch(&opts, path, &new_branch_to_free);
 		if (s)
 			branch = branch_to_free = s;
 		new_branch = new_branch_to_free;
@@ -904,10 +920,16 @@ static int add(int ac, const char **av, const char *prefix,
 
 		commit = lookup_commit_reference_by_name(branch);
 		if (!commit) {
-			remote = unique_tracking_name(branch, &oid, NULL);
+			int num_matches = 0;
+			remote = unique_tracking_name(branch, &oid, &num_matches);
 			if (remote) {
 				new_branch = branch;
 				branch = new_branch_to_free = remote;
+			} else if (num_matches > 1) {
+				if (!opts.quiet && advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) {
+					advise(_(message_advice_ambiguous_remote_tracking_branch));
+				}
+				die(_("'%s' matched multiple (%d) remote tracking branches"), branch, num_matches);
 			}
 		}
 
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 87b926728a..4d21c8eba4 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -624,12 +624,12 @@ test_expect_success '"add" <path> <branch> dwims' '
 test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' '
 	test_when_finished rm -rf repo_upstream repo_dwim foo &&
 	setup_remote_repo repo_upstream repo_dwim &&
-	git init repo_dwim &&
 	(
 		cd repo_dwim &&
 		git remote add repo_upstream2 ../repo_upstream &&
 		git fetch repo_upstream2 &&
-		test_must_fail git worktree add ../foo foo &&
+		test_must_fail git worktree add ../foo foo 2>error.actual &&
+		test_grep "matched multiple (2) remote tracking branches" error.actual &&
 		git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo &&
 		git status -uno --porcelain >status.actual &&
 		test_must_be_empty status.actual
@@ -669,6 +669,23 @@ test_expect_success 'git worktree add --guess-remote sets up tracking' '
 		test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
 	)
 '
+test_expect_success 'git worktree add --guess-remote with ambiguous name' '
+	test_when_finished rm -rf repo_a repo_b foo &&
+	setup_remote_repo repo_a repo_b &&
+	(
+		cd repo_b &&
+		git remote add upstream2 ../repo_a &&
+		git fetch upstream2 &&
+		git worktree add --guess-remote ../foo 2>actual &&
+		test_grep "matched multiple (2) remote tracking branches" actual
+	) &&
+	(
+		cd foo &&
+		test_must_fail git config "branch.foo.remote" &&
+		test_must_fail git config "branch.foo.merge" &&
+		test_cmp_rev refs/heads/main refs/heads/foo
+	)
+'
 test_expect_success 'git worktree add --guess-remote sets up tracking (quiet)' '
 	test_when_finished rm -rf repo_a repo_b foo &&
 	setup_remote_repo repo_a repo_b &&

base-commit: 010afd3166ddc64c9863b1506f12cbcdda0d4ea1
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-08  8:21 [PATCH] worktree add: improve message for ambiguous remote branch name Yoichi NAKAYAMA via GitGitGadget
@ 2026-08-08 17:00 ` Junio C Hamano
  2026-08-08 21:57   ` Junio C Hamano
  2026-08-10 13:00   ` Yoichi Nakayama
  2026-08-10 13:07 ` D. Ben Knoble
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 18+ messages in thread
From: Junio C Hamano @ 2026-08-08 17:00 UTC (permalink / raw)
  To: Yoichi NAKAYAMA via GitGitGadget; +Cc: git, Yoichi NAKAYAMA

"Yoichi NAKAYAMA via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
>
> Display a descriptive message when DWIM fails.
>
> Add advice on how to work around this by specifying the fully
> qualified name or by setting checkout.defaultRemote.
>
> Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
> ---
>     worktree add: improve message for ambiguous remote branch name
>
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2197%2Fyoichi%2Fimprove-worktree-add-error-message-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2197/yoichi/improve-worktree-add-error-message-v1
> Pull-Request: https://github.com/gitgitgadget/git/pull/2197
>
>  builtin/worktree.c      | 30 ++++++++++++++++++++++++++----
>  t/t2400-worktree-add.sh | 21 +++++++++++++++++++--
>  2 files changed, 45 insertions(+), 6 deletions(-)
>
> diff --git a/builtin/worktree.c b/builtin/worktree.c
> index 654d27c3e1..46bc305116 100644
> --- a/builtin/worktree.c
> +++ b/builtin/worktree.c
> @@ -116,6 +116,16 @@ static const char * const git_worktree_unlock_usage[] = {
>  	NULL
>  };
>  
> +static const char message_advice_ambiguous_remote_tracking_branch[] =
> +	N_("If you meant to create a worktree from a remote tracking branch on,\n"
> +	   "e.g. 'origin', you can do so by fully qualifying the name:\n"
> +	   "\n"
> +	   "    git worktree add <path> origin/<name>\n"
> +	   "\n"

This is shown in two places, but what did the user exactly type in
these two situations?  Can their intent be different, in which case
different suggestions might be more appropriate to each of them?

Let's see.

> @@ -781,8 +791,14 @@ static char *dwim_branch(const char *path, char **new_branch)
>  
>  	*new_branch = branchname;
>  	if (guess_remote) {
> +		int num_matches = 0;
>  		struct object_id oid;
> -		char *remote = unique_tracking_name(*new_branch, &oid, NULL);
> +		char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
> +		if (!opts->quiet && !remote && num_matches > 1) {
> +			if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
> +				advise(_(message_advice_ambiguous_remote_tracking_branch));
> +			warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
> +		}
>  		return remote;
>  	}

The worktree.guessremote configuration is set.  dwim_branch() is
called when "git worktree add A/B/X" is run with a single argument
"A/B/X", which comes here as "path", and that is munged into the
branchname "X".

We used to pass NULL as the second parameter to unique_tracking_name(),
so we were only interested in the case where we have exactly one
matching remote, and if there is 0 or multiple remotes with the
named branch, we returned NULL from here.

The patch does not change that, but using the branch name, we try to
see if there are multiple matches, in that case, we give the advice
message to say "hey, don't be so lazy, as X appears in more than one
remote, so tell me which one you mean".

> @@ -890,7 +906,7 @@ static int add(int ac, const char **av, const char *prefix,
>  		opts.orphan = dwim_orphan(&opts, !!opt_track, 0);
>  	} else if (ac < 2) {
>  		/* DWIM: Guess branch name from path. */
> -		char *s = dwim_branch(path, &new_branch_to_free);
> +		char *s = dwim_branch(&opts, path, &new_branch_to_free);
>  		if (s)
>  			branch = branch_to_free = s;
>  		new_branch = new_branch_to_free;

But shouldn't we do a bit better than 

    git worktree add <path> origin/<name>

The above makes the user think that just like 'git', 'worktree' and
'add', 'origin/' is a fixed part, and they would need to substitute
<path> and <name>, but that is not really what we want to tell them.
The most crucial part to correct is 'origin/', as that is what we
could not guess from the given information.

We know that the user gave us "A/B/X" (path) and probably they want
to create local "X" from it.  Or not.  We also should know, in
caller's opt_track and used_new_branch_options, that the user gave
us "-t -b Y" from the command line.

> @@ -904,10 +920,16 @@ static int add(int ac, const char **av, const char *prefix,
>  
>  		commit = lookup_commit_reference_by_name(branch);
>  		if (!commit) {
> -			remote = unique_tracking_name(branch, &oid, NULL);
> +			int num_matches = 0;
> +			remote = unique_tracking_name(branch, &oid, &num_matches);
>  			if (remote) {
>  				new_branch = branch;
>  				branch = new_branch_to_free = remote;
> +			} else if (num_matches > 1) {
> +				if (!opts.quiet && advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) {
> +					advise(_(message_advice_ambiguous_remote_tracking_branch));
> +				}
> +				die(_("'%s' matched multiple (%d) remote tracking branches"), branch, num_matches);

Style: overly long line, with {braces} around a single statement block.

What does this case handle?  Can you make a similar analysis to come
up with the list of things we know the user gave us, to give a bit
better command line to suggest here?

>  			}
>  		}

Thanks.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-08 17:00 ` Junio C Hamano
@ 2026-08-08 21:57   ` Junio C Hamano
  2026-08-09  7:45     ` Harald Nordgren
                       ` (2 more replies)
  2026-08-10 13:00   ` Yoichi Nakayama
  1 sibling, 3 replies; 18+ messages in thread
From: Junio C Hamano @ 2026-08-08 21:57 UTC (permalink / raw)
  To: Yoichi NAKAYAMA via GitGitGadget; +Cc: git, Yoichi NAKAYAMA

Junio C Hamano <gitster@pobox.com> writes:

>> +static const char message_advice_ambiguous_remote_tracking_branch[] =
>> +	N_("If you meant to create a worktree from a remote tracking branch on,\n"
>> +	   "e.g. 'origin', you can do so by fully qualifying the name:\n"
>> +	   "\n"
>> +	   "    git worktree add <path> origin/<name>\n"
>> +	   "\n"
>> ...
>> +		char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
>> +		if (!opts->quiet && !remote && num_matches > 1) {
>> +			if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
>> +				advise(_(message_advice_ambiguous_remote_tracking_branch));
>> +			warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
>> +		}
>>  		return remote;
>>  	}
>
> The worktree.guessremote configuration is set.  dwim_branch() is
> called when "git worktree add A/B/X" is run with a single argument
> "A/B/X", which comes here as "path", and that is munged into the
> branchname "X".
>
> We used to pass NULL as the second parameter to unique_tracking_name(),
> so we were only interested in the case where we have exactly one
> matching remote, and if there is 0 or multiple remotes with the
> named branch, we returned NULL from here.
>
> The patch does not change that, but using the branch name, we try to
> see if there are multiple matches, in that case, we give the advice
> message to say "hey, don't be so lazy, as X appears in more than one
> remote, so tell me which one you mean".

Stepping back a bit, I think what I find lacking in the proposed
warning message is not that we lose what the user gave us, such as
'-b <branch>' or '-t'.  While this loss makes it impossible to
simply copy and paste to reproduce what the user may have intended,
it is not the end of the world.

What disturbs me more is that the code holds back information only
it possesses, which would immediately help the user if we shared it.

The reason we got this error may not be that the user did not know
exactly how to spell out the necessary information (such as which
branch to use from which remote) on the command line.  It may be
that the user did not remember some of the necessary details (such
as which remotes have the branch they have in mind).  Displaying
the command line and advising them to use the fully qualified name
might not be the best approach in that case.  Telling them that
they may have meant 'origin', 'upstream', or 'home' (all of which
are remotes with the named branch, though we could not guess which
one of the three to choose) may be much more helpful.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-08 21:57   ` Junio C Hamano
@ 2026-08-09  7:45     ` Harald Nordgren
  2026-08-09 18:19       ` Junio C Hamano
  2026-08-09 18:17     ` Junio C Hamano
  2026-08-10 13:04     ` Yoichi Nakayama
  2 siblings, 1 reply; 18+ messages in thread
From: Harald Nordgren @ 2026-08-09  7:45 UTC (permalink / raw)
  To: gitster; +Cc: git, gitgitgadget, yoichi.nakayama

This is an interesting idea!


Harald

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-08 21:57   ` Junio C Hamano
  2026-08-09  7:45     ` Harald Nordgren
@ 2026-08-09 18:17     ` Junio C Hamano
  2026-08-10 13:04     ` Yoichi Nakayama
  2 siblings, 0 replies; 18+ messages in thread
From: Junio C Hamano @ 2026-08-09 18:17 UTC (permalink / raw)
  To: Yoichi NAKAYAMA via GitGitGadget; +Cc: git, Yoichi NAKAYAMA

Junio C Hamano <gitster@pobox.com> writes:

> Junio C Hamano <gitster@pobox.com> writes:
>
>>> +static const char message_advice_ambiguous_remote_tracking_branch[] =
>>> +	N_("If you meant to create a worktree from a remote tracking branch on,\n"
>>> +	   "e.g. 'origin', you can do so by fully qualifying the name:\n"
>>> +	   "\n"
>>> +	   "    git worktree add <path> origin/<name>\n"
>>> +	   "\n"
>>> ...
>>> +		char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
>>> +		if (!opts->quiet && !remote && num_matches > 1) {
>>> +			if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
>>> +				advise(_(message_advice_ambiguous_remote_tracking_branch));
>>> +			warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
>>> +		}

Sorry for piecemeal reviews, but I just noticed that you have a
terminating LF at the end of a single-liner warning message.  As
die/error/warning ffamily of helpers give the terminating newline
themselves, you must not.  Unless you want to leave a blank line
after your message, that is.

Thanks.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-09  7:45     ` Harald Nordgren
@ 2026-08-09 18:19       ` Junio C Hamano
  2026-08-10 10:12         ` Harald Nordgren
  0 siblings, 1 reply; 18+ messages in thread
From: Junio C Hamano @ 2026-08-09 18:19 UTC (permalink / raw)
  To: Harald Nordgren; +Cc: git, gitgitgadget, yoichi.nakayama

Harald Nordgren <haraldnordgren@gmail.com> writes:

> This is an interesting idea!
>
>
> Harald

When expressing your opinion on what another said, quote a bit from
the message you are responding to so that people know what you are
referring to.  I cannot easily tell which part of what I said you
found interesting.

Thanks.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-09 18:19       ` Junio C Hamano
@ 2026-08-10 10:12         ` Harald Nordgren
  0 siblings, 0 replies; 18+ messages in thread
From: Harald Nordgren @ 2026-08-10 10:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, gitgitgadget, yoichi.nakayama

> When expressing your opinion on what another said, quote a bit from
> the message you are responding to so that people know what you are
> referring to.  I cannot easily tell which part of what I said you
> found interesting.

Sorry, yes this was about:

> Telling them that
> they may have meant 'origin', 'upstream', or 'home' (all of which
> are remotes with the named branch, though we could not guess which
> one of the three to choose) may be much more helpful.

Harald

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-08 17:00 ` Junio C Hamano
  2026-08-08 21:57   ` Junio C Hamano
@ 2026-08-10 13:00   ` Yoichi Nakayama
  1 sibling, 0 replies; 18+ messages in thread
From: Yoichi Nakayama @ 2026-08-10 13:00 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Yoichi NAKAYAMA via GitGitGadget, git

On Sun, Aug 9, 2026 at 2:00 AM Junio C Hamano <gitster@pobox.com> wrote:
> > @@ -781,8 +791,14 @@ static char *dwim_branch(const char *path, char **new_branch)
> >
> >       *new_branch = branchname;
> >       if (guess_remote) {
> > +             int num_matches = 0;
> >               struct object_id oid;
> > -             char *remote = unique_tracking_name(*new_branch, &oid, NULL);
> > +             char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
> > +             if (!opts->quiet && !remote && num_matches > 1) {
> > +                     if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
> > +                             advise(_(message_advice_ambiguous_remote_tracking_branch));
> > +                     warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
> > +             }
> >               return remote;
> >       }
>
> The worktree.guessremote configuration is set.  dwim_branch() is
> called when "git worktree add A/B/X" is run with a single argument
> "A/B/X", which comes here as "path", and that is munged into the
> branchname "X".
>
> We used to pass NULL as the second parameter to unique_tracking_name(),
> so we were only interested in the case where we have exactly one
> matching remote, and if there is 0 or multiple remotes with the
> named branch, we returned NULL from here.
>
> The patch does not change that, but using the branch name, we try to
> see if there are multiple matches, in that case, we give the advice
> message to say "hey, don't be so lazy, as X appears in more than one
> remote, so tell me which one you mean".

I thought the problem here was that it was impossible to distinguish whether
the guess was successful, but it was not true. We can distinguish by
the message:
    branch 'name' set up to track 'remote/name'.
I will not make changes to this part.

Thanks,
-- 
Yoichi NAKAYAMA

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-08 21:57   ` Junio C Hamano
  2026-08-09  7:45     ` Harald Nordgren
  2026-08-09 18:17     ` Junio C Hamano
@ 2026-08-10 13:04     ` Yoichi Nakayama
  2 siblings, 0 replies; 18+ messages in thread
From: Yoichi Nakayama @ 2026-08-10 13:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Yoichi NAKAYAMA via GitGitGadget, git

On Sun, Aug 9, 2026 at 6:57 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Junio C Hamano <gitster@pobox.com> writes:
>
> >> +static const char message_advice_ambiguous_remote_tracking_branch[] =
> >> +    N_("If you meant to create a worktree from a remote tracking branch on,\n"
> >> +       "e.g. 'origin', you can do so by fully qualifying the name:\n"
> >> +       "\n"
> >> +       "    git worktree add <path> origin/<name>\n"
> >> +       "\n"
> >> ...
> >> +            char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
> >> +            if (!opts->quiet && !remote && num_matches > 1) {
> >> +                    if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
> >> +                            advise(_(message_advice_ambiguous_remote_tracking_branch));
> >> +                    warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
> >> +            }
> >>              return remote;
> >>      }
> >
> > The worktree.guessremote configuration is set.  dwim_branch() is
> > called when "git worktree add A/B/X" is run with a single argument
> > "A/B/X", which comes here as "path", and that is munged into the
> > branchname "X".
> >
> > We used to pass NULL as the second parameter to unique_tracking_name(),
> > so we were only interested in the case where we have exactly one
> > matching remote, and if there is 0 or multiple remotes with the
> > named branch, we returned NULL from here.
> >
> > The patch does not change that, but using the branch name, we try to
> > see if there are multiple matches, in that case, we give the advice
> > message to say "hey, don't be so lazy, as X appears in more than one
> > remote, so tell me which one you mean".
>
> Stepping back a bit, I think what I find lacking in the proposed
> warning message is not that we lose what the user gave us, such as
> '-b <branch>' or '-t'.  While this loss makes it impossible to
> simply copy and paste to reproduce what the user may have intended,
> it is not the end of the world.
>
> What disturbs me more is that the code holds back information only
> it possesses, which would immediately help the user if we shared it.
>
> The reason we got this error may not be that the user did not know
> exactly how to spell out the necessary information (such as which
> branch to use from which remote) on the command line.  It may be
> that the user did not remember some of the necessary details (such
> as which remotes have the branch they have in mind).  Displaying
> the command line and advising them to use the fully qualified name
> might not be the best approach in that case.  Telling them that
> they may have meant 'origin', 'upstream', or 'home' (all of which
> are remotes with the named branch, though we could not guess which
> one of the three to choose) may be much more helpful.

I realized that instead of placing a burden on the user, we should
present a solution.

When a multiple match occurs, the only decision the user needs to make
is which remote to select.
For everything else, the hint should give a specific command with
arguments that achieve the same
behavior as when exactly one remote matches.

Rather than presenting a list of candidates, I think it is preferable
to explain how to generate that list.
This allows users to process the list e.g. by piping it into a command.

I'll submit an updated patch.

Thanks,
-- 
Yoichi NAKAYAMA

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-08  8:21 [PATCH] worktree add: improve message for ambiguous remote branch name Yoichi NAKAYAMA via GitGitGadget
  2026-08-08 17:00 ` Junio C Hamano
@ 2026-08-10 13:07 ` D. Ben Knoble
  2026-08-10 13:35   ` Yoichi Nakayama
  2026-08-10 21:36   ` Yoichi Nakayama
  2026-08-10 15:07 ` [PATCH v2] " Yoichi NAKAYAMA via GitGitGadget
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 18+ messages in thread
From: D. Ben Knoble @ 2026-08-10 13:07 UTC (permalink / raw)
  To: Yoichi NAKAYAMA via GitGitGadget
  Cc: git, Yoichi NAKAYAMA, Junio C Hamano, Harald Nordgren

Hi Yoichi,

On Sat, Aug 8, 2026 at 4:21 AM Yoichi NAKAYAMA via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
>
> Display a descriptive message when DWIM fails.
>
> Add advice on how to work around this by specifying the fully
> qualified name or by setting checkout.defaultRemote.
>
> Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
> ---

[snip]

> -static char *dwim_branch(const char *path, char **new_branch)
> +static char *dwim_branch(const struct add_opts *opts, const char *path, char **new_branch)
>  {
>         int n;
>         int branch_exists;
> @@ -781,8 +791,14 @@ static char *dwim_branch(const char *path, char **new_branch)
>
>         *new_branch = branchname;
>         if (guess_remote) {
> +               int num_matches = 0;
>                 struct object_id oid;
> -               char *remote = unique_tracking_name(*new_branch, &oid, NULL);
> +               char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
> +               if (!opts->quiet && !remote && num_matches > 1) {
> +                       if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
> +                               advise(_(message_advice_ambiguous_remote_tracking_branch));
> +                       warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
> +               }
>                 return remote;
>         }
>         return NULL;

I suppose the extra warning won't hurt anyone's workflow :) so that's good.

[snip]

> @@ -904,10 +920,16 @@ static int add(int ac, const char **av, const char *prefix,
>
>                 commit = lookup_commit_reference_by_name(branch);
>                 if (!commit) {
> -                       remote = unique_tracking_name(branch, &oid, NULL);
> +                       int num_matches = 0;
> +                       remote = unique_tracking_name(branch, &oid, &num_matches);
>                         if (remote) {
>                                 new_branch = branch;
>                                 branch = new_branch_to_free = remote;
> +                       } else if (num_matches > 1) {
> +                               if (!opts.quiet && advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) {
> +                                       advise(_(message_advice_ambiguous_remote_tracking_branch));
> +                               }
> +                               die(_("'%s' matched multiple (%d) remote tracking branches"), branch, num_matches);
>                         }
>                 }

We would now die() here where we didn't before. I'm not suggesting
that is wrong (I haven't given it much thought), but I was surprised
to see it in the code without mention in the message, which I've left
quoted above. In particular, the proposed log message talks about
giving new advice, so I wasn't expecting us to abort.

Now, it may be that this case already causes an error later on (I
haven't analyzed that), in which case dying early with a better
diagnostic is definitely helpful. If that's the case, it would be nice
to spell that out for the rest of us :)

If not, I would want to know why we can die() here without bothering
anyone's workflow that is expecting us to carry on.

Thanks!

-- 
D. Ben Knoble

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-10 13:07 ` D. Ben Knoble
@ 2026-08-10 13:35   ` Yoichi Nakayama
  2026-08-10 15:06     ` Junio C Hamano
  2026-08-10 21:36   ` Yoichi Nakayama
  1 sibling, 1 reply; 18+ messages in thread
From: Yoichi Nakayama @ 2026-08-10 13:35 UTC (permalink / raw)
  To: D. Ben Knoble
  Cc: Yoichi NAKAYAMA via GitGitGadget, git, Junio C Hamano,
	Harald Nordgren

On Mon, Aug 10, 2026 at 10:08 PM D. Ben Knoble <ben.knoble@gmail.com> wrote:
> > @@ -904,10 +920,16 @@ static int add(int ac, const char **av, const char *prefix,
> >
> >                 commit = lookup_commit_reference_by_name(branch);
> >                 if (!commit) {
> > -                       remote = unique_tracking_name(branch, &oid, NULL);
> > +                       int num_matches = 0;
> > +                       remote = unique_tracking_name(branch, &oid, &num_matches);
> >                         if (remote) {
> >                                 new_branch = branch;
> >                                 branch = new_branch_to_free = remote;
> > +                       } else if (num_matches > 1) {
> > +                               if (!opts.quiet && advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) {
> > +                                       advise(_(message_advice_ambiguous_remote_tracking_branch));
> > +                               }
> > +                               die(_("'%s' matched multiple (%d) remote tracking branches"), branch, num_matches);
> >                         }
> >                 }
>
> We would now die() here where we didn't before. I'm not suggesting
> that is wrong (I haven't given it much thought), but I was surprised
> to see it in the code without mention in the message, which I've left
> quoted above. In particular, the proposed log message talks about
> giving new advice, so I wasn't expecting us to abort.
>
> Now, it may be that this case already causes an error later on (I
> haven't analyzed that), in which case dying early with a better
> diagnostic is definitely helpful. If that's the case, it would be nice
> to spell that out for the rest of us :)
>
> If not, I would want to know why we can die() here without bothering
> anyone's workflow that is expecting us to carry on.

Before the change, it calles lookup_commit_reference_by_name() again
in the if condition and die() at:

    if (!opts.orphan && !lookup_commit_reference_by_name(branch)) {
        /* snip */
        die(_("invalid reference: %s"), branch);
    }

The motivation for the fix was that this error message did not
accurately reflect the situation.

Thanks,
-- 
Yoichi NAKAYAMA

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-10 13:35   ` Yoichi Nakayama
@ 2026-08-10 15:06     ` Junio C Hamano
  0 siblings, 0 replies; 18+ messages in thread
From: Junio C Hamano @ 2026-08-10 15:06 UTC (permalink / raw)
  To: Yoichi Nakayama
  Cc: D. Ben Knoble, Yoichi NAKAYAMA via GitGitGadget, git,
	Harald Nordgren

Yoichi Nakayama <yoichi.nakayama@gmail.com> writes:

> Before the change, it calles lookup_commit_reference_by_name() again
> in the if condition and die() at:
>
>     if (!opts.orphan && !lookup_commit_reference_by_name(branch)) {
>         /* snip */
>         die(_("invalid reference: %s"), branch);
>     }
>
> The motivation for the fix was that this error message did not
> accurately reflect the situation.

The location of this die() is a tad away from the places that the
patch touched.  The proposed log message could be made a bit more
helpful by mentioning it.  What was posted reads:

    Display a descriptive message when DWIM fails.

    Add advice on how to work around this by specifying the fully
    qualified name or by setting checkout.defaultRemote.

but telling the readers what they will see instead of a descriptive
message and how that happens would be very helpful to understand why
it is a good idea to die early.  Perhaps

    When the user runs 'git worktree add x y z' command that does
    not exactly say which remote they want to work with, we try to
    guess which remote by passing y.  If there are multiple remotes
    that have branch named y, we silently gave up, leaving remote
    still NULL.  This later causes A and B not happen, and we end up
    with passing an non-existing branch to
    lookup_commit_reference_by_name(), triggering "invalid
    reference" error and die.

or something like that that describes the issue to a similar degree
as above mock-up message.

Thanks.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2] worktree add: improve message for ambiguous remote branch name
  2026-08-08  8:21 [PATCH] worktree add: improve message for ambiguous remote branch name Yoichi NAKAYAMA via GitGitGadget
  2026-08-08 17:00 ` Junio C Hamano
  2026-08-10 13:07 ` D. Ben Knoble
@ 2026-08-10 15:07 ` Yoichi NAKAYAMA via GitGitGadget
  2026-08-10 20:55 ` [PATCH v3] " Yoichi NAKAYAMA via GitGitGadget
  2026-08-11  6:35 ` [PATCH v4] " Yoichi NAKAYAMA via GitGitGadget
  4 siblings, 0 replies; 18+ messages in thread
From: Yoichi NAKAYAMA via GitGitGadget @ 2026-08-10 15:07 UTC (permalink / raw)
  To: git
  Cc: Harald Nordgren, Yoichi Nakayama, D. Ben Knoble, Yoichi NAKAYAMA,
	Yoichi NAKAYAMA

From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>

Display a hint and a descriptive error message when DWIM fails.

Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
---
    worktree add: improve message for ambiguous remote branch name

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2197%2Fyoichi%2Fimprove-worktree-add-error-message-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2197/yoichi/improve-worktree-add-error-message-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/2197

Range-diff vs v1:

 1:  00b814fe09 ! 1:  1bc57ce497 worktree add: improve message for ambiguous remote branch name
     @@ Metadata
       ## Commit message ##
          worktree add: improve message for ambiguous remote branch name
      
     -    Display a descriptive message when DWIM fails.
     -
     -    Add advice on how to work around this by specifying the fully
     -    qualified name or by setting checkout.defaultRemote.
     +    Display a hint and a descriptive error message when DWIM fails.
      
          Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
      
       ## builtin/worktree.c ##
     -@@ builtin/worktree.c: static const char * const git_worktree_unlock_usage[] = {
     - 	NULL
     - };
     +@@
     + 	"\n" \
     + 	"    git worktree add --orphan %s\n")
       
     -+static const char message_advice_ambiguous_remote_tracking_branch[] =
     -+	N_("If you meant to create a worktree from a remote tracking branch on,\n"
     -+	   "e.g. 'origin', you can do so by fully qualifying the name:\n"
     -+	   "\n"
     -+	   "    git worktree add <path> origin/<name>\n"
     -+	   "\n"
     -+	   "If you'd like to always have checkouts of an ambiguous <name> prefer\n"
     -+	   "one remote, e.g. the 'origin' remote, consider setting\n"
     -+	   "checkout.defaultRemote=origin in your config.");
     ++#define WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT \
     ++	_("Matched multiple remote tracking branches, you can list them by:\n" \
     ++	"\n" \
     ++	"    git branch -r --list \"*/%s\"\n" \
     ++	"\n" \
     ++	"If you meant to create a worktree from a remote tracking branch on,\n" \
     ++	"e.g. 'origin', you can do so by:\n" \
     ++	"\n" \
     ++	"    git worktree add -b %s %s origin/%s\n" \
     ++	"\n" \
     ++	"If you'd like to always prefer some remote, e.g. 'origin',\n" \
     ++	"consider setting checkout.defaultRemote=origin in your config.")
      +
     - struct add_opts {
     - 	int force;
     - 	int detach;
     -@@ builtin/worktree.c: static int dwim_orphan(const struct add_opts *opts, int opt_track, int remote)
     - 	return 1;
     - }
     - 
     --static char *dwim_branch(const char *path, char **new_branch)
     -+static char *dwim_branch(const struct add_opts *opts, const char *path, char **new_branch)
     - {
     - 	int n;
     - 	int branch_exists;
     -@@ builtin/worktree.c: static char *dwim_branch(const char *path, char **new_branch)
     - 
     - 	*new_branch = branchname;
     - 	if (guess_remote) {
     -+		int num_matches = 0;
     - 		struct object_id oid;
     --		char *remote = unique_tracking_name(*new_branch, &oid, NULL);
     -+		char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
     -+		if (!opts->quiet && !remote && num_matches > 1) {
     -+			if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
     -+				advise(_(message_advice_ambiguous_remote_tracking_branch));
     -+			warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
     -+		}
     - 		return remote;
     - 	}
     - 	return NULL;
     -@@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix,
     - 		opts.orphan = dwim_orphan(&opts, !!opt_track, 0);
     - 	} else if (ac < 2) {
     - 		/* DWIM: Guess branch name from path. */
     --		char *s = dwim_branch(path, &new_branch_to_free);
     -+		char *s = dwim_branch(&opts, path, &new_branch_to_free);
     - 		if (s)
     - 			branch = branch_to_free = s;
     - 		new_branch = new_branch_to_free;
     + static const char * const git_worktree_usage[] = {
     + 	BUILTIN_WORKTREE_ADD_USAGE,
     + 	BUILTIN_WORKTREE_LIST_USAGE,
      @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix,
       
       		commit = lookup_commit_reference_by_name(branch);
     @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix,
       				new_branch = branch;
       				branch = new_branch_to_free = remote;
      +			} else if (num_matches > 1) {
     -+				if (!opts.quiet && advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) {
     -+					advise(_(message_advice_ambiguous_remote_tracking_branch));
     -+				}
     -+				die(_("'%s' matched multiple (%d) remote tracking branches"), branch, num_matches);
     ++				if (!opts.quiet)
     ++					advise_if_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
     ++							  WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT,
     ++							  branch, branch, path, branch);
     ++				die(_("'%s' matched multiple (%d) remote tracking branches"),
     ++				    branch, num_matches);
       			}
       		}
       
     @@ t/t2400-worktree-add.sh: test_expect_success '"add" <path> <branch> dwims' '
       		git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo &&
       		git status -uno --porcelain >status.actual &&
       		test_must_be_empty status.actual
     -@@ t/t2400-worktree-add.sh: test_expect_success 'git worktree add --guess-remote sets up tracking' '
     - 		test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
     - 	)
     - '
     -+test_expect_success 'git worktree add --guess-remote with ambiguous name' '
     -+	test_when_finished rm -rf repo_a repo_b foo &&
     -+	setup_remote_repo repo_a repo_b &&
     -+	(
     -+		cd repo_b &&
     -+		git remote add upstream2 ../repo_a &&
     -+		git fetch upstream2 &&
     -+		git worktree add --guess-remote ../foo 2>actual &&
     -+		test_grep "matched multiple (2) remote tracking branches" actual
     -+	) &&
     -+	(
     -+		cd foo &&
     -+		test_must_fail git config "branch.foo.remote" &&
     -+		test_must_fail git config "branch.foo.merge" &&
     -+		test_cmp_rev refs/heads/main refs/heads/foo
     -+	)
     -+'
     - test_expect_success 'git worktree add --guess-remote sets up tracking (quiet)' '
     - 	test_when_finished rm -rf repo_a repo_b foo &&
     - 	setup_remote_repo repo_a repo_b &&


 builtin/worktree.c      | 23 ++++++++++++++++++++++-
 t/t2400-worktree-add.sh |  4 ++--
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 654d27c3e1..b29c3a3755 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -64,6 +64,19 @@
 	"\n" \
 	"    git worktree add --orphan %s\n")
 
+#define WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT \
+	_("Matched multiple remote tracking branches, you can list them by:\n" \
+	"\n" \
+	"    git branch -r --list \"*/%s\"\n" \
+	"\n" \
+	"If you meant to create a worktree from a remote tracking branch on,\n" \
+	"e.g. 'origin', you can do so by:\n" \
+	"\n" \
+	"    git worktree add -b %s %s origin/%s\n" \
+	"\n" \
+	"If you'd like to always prefer some remote, e.g. 'origin',\n" \
+	"consider setting checkout.defaultRemote=origin in your config.")
+
 static const char * const git_worktree_usage[] = {
 	BUILTIN_WORKTREE_ADD_USAGE,
 	BUILTIN_WORKTREE_LIST_USAGE,
@@ -904,10 +917,18 @@ static int add(int ac, const char **av, const char *prefix,
 
 		commit = lookup_commit_reference_by_name(branch);
 		if (!commit) {
-			remote = unique_tracking_name(branch, &oid, NULL);
+			int num_matches = 0;
+			remote = unique_tracking_name(branch, &oid, &num_matches);
 			if (remote) {
 				new_branch = branch;
 				branch = new_branch_to_free = remote;
+			} else if (num_matches > 1) {
+				if (!opts.quiet)
+					advise_if_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
+							  WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT,
+							  branch, branch, path, branch);
+				die(_("'%s' matched multiple (%d) remote tracking branches"),
+				    branch, num_matches);
 			}
 		}
 
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 87b926728a..5c105cf252 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -624,12 +624,12 @@ test_expect_success '"add" <path> <branch> dwims' '
 test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' '
 	test_when_finished rm -rf repo_upstream repo_dwim foo &&
 	setup_remote_repo repo_upstream repo_dwim &&
-	git init repo_dwim &&
 	(
 		cd repo_dwim &&
 		git remote add repo_upstream2 ../repo_upstream &&
 		git fetch repo_upstream2 &&
-		test_must_fail git worktree add ../foo foo &&
+		test_must_fail git worktree add ../foo foo 2>error.actual &&
+		test_grep "matched multiple (2) remote tracking branches" error.actual &&
 		git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo &&
 		git status -uno --porcelain >status.actual &&
 		test_must_be_empty status.actual

base-commit: 010afd3166ddc64c9863b1506f12cbcdda0d4ea1
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v3] worktree add: improve message for ambiguous remote branch name
  2026-08-08  8:21 [PATCH] worktree add: improve message for ambiguous remote branch name Yoichi NAKAYAMA via GitGitGadget
                   ` (2 preceding siblings ...)
  2026-08-10 15:07 ` [PATCH v2] " Yoichi NAKAYAMA via GitGitGadget
@ 2026-08-10 20:55 ` Yoichi NAKAYAMA via GitGitGadget
  2026-08-11  0:03   ` Junio C Hamano
  2026-08-11  6:35 ` [PATCH v4] " Yoichi NAKAYAMA via GitGitGadget
  4 siblings, 1 reply; 18+ messages in thread
From: Yoichi NAKAYAMA via GitGitGadget @ 2026-08-10 20:55 UTC (permalink / raw)
  To: git
  Cc: Harald Nordgren, Yoichi Nakayama, D. Ben Knoble, Yoichi NAKAYAMA,
	Yoichi NAKAYAMA

From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>

When the user runs 'git worktree add x y' command that does not
exactly say which remote they want to work with, and there is no local
branch named y, we try to guess which remote by passing y then create
a new branch named y which tracks the remote branch.

If there are multiple remotes that have branch named y, we silently
gave up, leaving the variable branch intact.  This later causes
creating local branch and worktree not happen, and we end up with
passing an non-existing branch to lookup_commit_reference_by_name(),
triggering "invalid reference" error and die.

To resolve this issue, display a hint and a descriptive error message
and die immediately when multiple mathing branches are found.

Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
---
    worktree add: improve message for ambiguous remote branch name

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2197%2Fyoichi%2Fimprove-worktree-add-error-message-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2197/yoichi/improve-worktree-add-error-message-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/2197

Range-diff vs v2:

 1:  1bc57ce497 ! 1:  1b9364da7e worktree add: improve message for ambiguous remote branch name
     @@ Metadata
       ## Commit message ##
          worktree add: improve message for ambiguous remote branch name
      
     -    Display a hint and a descriptive error message when DWIM fails.
     +    When the user runs 'git worktree add x y' command that does not
     +    exactly say which remote they want to work with, and there is no local
     +    branch named y, we try to guess which remote by passing y then create
     +    a new branch named y which tracks the remote branch.
     +
     +    If there are multiple remotes that have branch named y, we silently
     +    gave up, leaving the variable branch intact.  This later causes
     +    creating local branch and worktree not happen, and we end up with
     +    passing an non-existing branch to lookup_commit_reference_by_name(),
     +    triggering "invalid reference" error and die.
     +
     +    To resolve this issue, display a hint and a descriptive error message
     +    and die immediately when multiple mathing branches are found.
      
          Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
      


 builtin/worktree.c      | 23 ++++++++++++++++++++++-
 t/t2400-worktree-add.sh |  4 ++--
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 654d27c3e1..b29c3a3755 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -64,6 +64,19 @@
 	"\n" \
 	"    git worktree add --orphan %s\n")
 
+#define WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT \
+	_("Matched multiple remote tracking branches, you can list them by:\n" \
+	"\n" \
+	"    git branch -r --list \"*/%s\"\n" \
+	"\n" \
+	"If you meant to create a worktree from a remote tracking branch on,\n" \
+	"e.g. 'origin', you can do so by:\n" \
+	"\n" \
+	"    git worktree add -b %s %s origin/%s\n" \
+	"\n" \
+	"If you'd like to always prefer some remote, e.g. 'origin',\n" \
+	"consider setting checkout.defaultRemote=origin in your config.")
+
 static const char * const git_worktree_usage[] = {
 	BUILTIN_WORKTREE_ADD_USAGE,
 	BUILTIN_WORKTREE_LIST_USAGE,
@@ -904,10 +917,18 @@ static int add(int ac, const char **av, const char *prefix,
 
 		commit = lookup_commit_reference_by_name(branch);
 		if (!commit) {
-			remote = unique_tracking_name(branch, &oid, NULL);
+			int num_matches = 0;
+			remote = unique_tracking_name(branch, &oid, &num_matches);
 			if (remote) {
 				new_branch = branch;
 				branch = new_branch_to_free = remote;
+			} else if (num_matches > 1) {
+				if (!opts.quiet)
+					advise_if_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
+							  WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT,
+							  branch, branch, path, branch);
+				die(_("'%s' matched multiple (%d) remote tracking branches"),
+				    branch, num_matches);
 			}
 		}
 
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 87b926728a..5c105cf252 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -624,12 +624,12 @@ test_expect_success '"add" <path> <branch> dwims' '
 test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' '
 	test_when_finished rm -rf repo_upstream repo_dwim foo &&
 	setup_remote_repo repo_upstream repo_dwim &&
-	git init repo_dwim &&
 	(
 		cd repo_dwim &&
 		git remote add repo_upstream2 ../repo_upstream &&
 		git fetch repo_upstream2 &&
-		test_must_fail git worktree add ../foo foo &&
+		test_must_fail git worktree add ../foo foo 2>error.actual &&
+		test_grep "matched multiple (2) remote tracking branches" error.actual &&
 		git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo &&
 		git status -uno --porcelain >status.actual &&
 		test_must_be_empty status.actual

base-commit: 010afd3166ddc64c9863b1506f12cbcdda0d4ea1
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH] worktree add: improve message for ambiguous remote branch name
  2026-08-10 13:07 ` D. Ben Knoble
  2026-08-10 13:35   ` Yoichi Nakayama
@ 2026-08-10 21:36   ` Yoichi Nakayama
  1 sibling, 0 replies; 18+ messages in thread
From: Yoichi Nakayama @ 2026-08-10 21:36 UTC (permalink / raw)
  To: D. Ben Knoble
  Cc: Yoichi NAKAYAMA via GitGitGadget, git, Junio C Hamano,
	Harald Nordgren

On Mon, Aug 10, 2026 at 10:08 PM D. Ben Knoble <ben.knoble@gmail.com> wrote:
> > -static char *dwim_branch(const char *path, char **new_branch)
> > +static char *dwim_branch(const struct add_opts *opts, const char *path, char **new_branch)
> >  {
> >         int n;
> >         int branch_exists;
> > @@ -781,8 +791,14 @@ static char *dwim_branch(const char *path, char **new_branch)
> >
> >         *new_branch = branchname;
> >         if (guess_remote) {
> > +               int num_matches = 0;
> >                 struct object_id oid;
> > -               char *remote = unique_tracking_name(*new_branch, &oid, NULL);
> > +               char *remote = unique_tracking_name(*new_branch, &oid, &num_matches);
> > +               if (!opts->quiet && !remote && num_matches > 1) {
> > +                       if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
> > +                               advise(_(message_advice_ambiguous_remote_tracking_branch));
> > +                       warning(_("'%s' matched multiple (%d) remote tracking branches\n"), branchname, num_matches);
> > +               }
> >                 return remote;
> >         }
> >         return NULL;
>
> I suppose the extra warning won't hurt anyone's workflow :) so that's good.

I removed the change (advise and warn) here in the latest patch. But I am still
wondering what I should do. I think a warning would be excessive if
there is no match,
but the user might want to know if there are multiple matches.

Thanks,
-- 
Yoichi NAKAYAMA

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v3] worktree add: improve message for ambiguous remote branch name
  2026-08-10 20:55 ` [PATCH v3] " Yoichi NAKAYAMA via GitGitGadget
@ 2026-08-11  0:03   ` Junio C Hamano
  2026-08-11  6:31     ` Yoichi Nakayama
  0 siblings, 1 reply; 18+ messages in thread
From: Junio C Hamano @ 2026-08-11  0:03 UTC (permalink / raw)
  To: Yoichi NAKAYAMA via GitGitGadget
  Cc: git, Harald Nordgren, Yoichi Nakayama, D. Ben Knoble

"Yoichi NAKAYAMA via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
>
> When the user runs 'git worktree add x y' command that does not
> exactly say which remote they want to work with, and there is no local
> branch named y, we try to guess which remote by passing y then create
> a new branch named y which tracks the remote branch.

I used x and y as placeholders.  The readers would be helped if you
used a more plausible sounding names, e.g., naming directory as
something like foo-dir (the point being 'dir' somewhere in its name)
and naming a branch as something like bar-topic.  If this were 'git
worktree add', it is probably more than likely that the destination
directory would begin with ../ to have the new worktree next to the
primary repository we are running in, no?

> If there are multiple remotes that have branch named y, we silently
> gave up, leaving the variable branch intact.  This later causes
> creating local branch and worktree not happen, and we end up with
> passing an non-existing branch to lookup_commit_reference_by_name(),
> triggering "invalid reference" error and die.

"This later causes" part still seems a bit too sketchy to help a
totally new reader, even though I've stared at this code long enough
so it would be sufficient for me personally.  But these logs are not
about helping me, but helping other developers, so...

> +#define WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT \
> +	_("Matched multiple remote tracking branches, you can list them by:\n" \
> +	"\n" \
> +	"    git branch -r --list \"*/%s\"\n" \
> +	"\n" \
> +	"If you meant to create a worktree from a remote tracking branch on,\n" \
> +	"e.g. 'origin', you can do so by:\n" \
> +	"\n" \
> +	"    git worktree add -b %s %s origin/%s\n" \
> +	"\n" \
> +	"If you'd like to always prefer some remote, e.g. 'origin',\n" \
> +	"consider setting checkout.defaultRemote=origin in your config.")

Instead of throwing the problem back to the user with four extra
lines of message telling them how to run 'git branch', I would have
expected this patch to teach unique_tracking_name() to optionally
return the list of remotes with that branch name, and to use that
result in this message.  However, if the goal is simply to provide
something better than 'invalid reference', we do not even need to
go that far.  Just stating that branch 'y' appears on multiple
remotes and asking them to clarify which one they mean might be a
sufficient improvement.

Could the original request be aiming to create a new worktree with
the HEAD detached at the commit pointed at by the remote-tracking
branch, instead of creating a local branch forked from it?  I am
just wondering if "-b %s" is too specific to one possible
interpretation that may contradict to what the user actually wanted
to do.

Thanks.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v3] worktree add: improve message for ambiguous remote branch name
  2026-08-11  0:03   ` Junio C Hamano
@ 2026-08-11  6:31     ` Yoichi Nakayama
  0 siblings, 0 replies; 18+ messages in thread
From: Yoichi Nakayama @ 2026-08-11  6:31 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Yoichi NAKAYAMA via GitGitGadget, git, Harald Nordgren,
	D. Ben Knoble

On Tue, Aug 11, 2026 at 9:04 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Yoichi NAKAYAMA via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
> >
> > When the user runs 'git worktree add x y' command that does not
> > exactly say which remote they want to work with, and there is no local
> > branch named y, we try to guess which remote by passing y then create
> > a new branch named y which tracks the remote branch.
>
> I used x and y as placeholders.  The readers would be helped if you
> used a more plausible sounding names, e.g., naming directory as
> something like foo-dir (the point being 'dir' somewhere in its name)
> and naming a branch as something like bar-topic.  If this were 'git
> worktree add', it is probably more than likely that the destination
> directory would begin with ../ to have the new worktree next to the
> primary repository we are running in, no?
>
> > If there are multiple remotes that have branch named y, we silently
> > gave up, leaving the variable branch intact.  This later causes
> > creating local branch and worktree not happen, and we end up with
> > passing an non-existing branch to lookup_commit_reference_by_name(),
> > triggering "invalid reference" error and die.
>
> "This later causes" part still seems a bit too sketchy to help a
> totally new reader, even though I've stared at this code long enough
> so it would be sufficient for me personally.  But these logs are not
> about helping me, but helping other developers, so...
>
> > +#define WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT \
> > +     _("Matched multiple remote tracking branches, you can list them by:\n" \
> > +     "\n" \
> > +     "    git branch -r --list \"*/%s\"\n" \
> > +     "\n" \
> > +     "If you meant to create a worktree from a remote tracking branch on,\n" \
> > +     "e.g. 'origin', you can do so by:\n" \
> > +     "\n" \
> > +     "    git worktree add -b %s %s origin/%s\n" \
> > +     "\n" \
> > +     "If you'd like to always prefer some remote, e.g. 'origin',\n" \
> > +     "consider setting checkout.defaultRemote=origin in your config.")
>
> Instead of throwing the problem back to the user with four extra
> lines of message telling them how to run 'git branch', I would have
> expected this patch to teach unique_tracking_name() to optionally
> return the list of remotes with that branch name, and to use that
> result in this message.  However, if the goal is simply to provide
> something better than 'invalid reference', we do not even need to
> go that far.  Just stating that branch 'y' appears on multiple
> remotes and asking them to clarify which one they mean might be a
> sufficient improvement.

Extending `unique_tracking_name()` would also affect the implementation
in `checkout.c`, and since the goal here is to improve the messages
(making them as helpful as those in `checkout`), I will hold off on doing
that for now.

I will rewrite the log messages a bit.


> Could the original request be aiming to create a new worktree with
> the HEAD detached at the commit pointed at by the remote-tracking
> branch, instead of creating a local branch forked from it?  I am
> just wondering if "-b %s" is too specific to one possible
> interpretation that may contradict to what the user actually wanted
> to do.

If the user is aiming to create a new worktree with the HEAD detached,
one would specify a fully qualified branch name like origin/bar-topic,
starting with a remote name.  If a branch name starts with a remote name,
multiple matches (condition to show this hint) rarely occur.

Thanks,
-- 
Yoichi NAKAYAMA

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v4] worktree add: improve message for ambiguous remote branch name
  2026-08-08  8:21 [PATCH] worktree add: improve message for ambiguous remote branch name Yoichi NAKAYAMA via GitGitGadget
                   ` (3 preceding siblings ...)
  2026-08-10 20:55 ` [PATCH v3] " Yoichi NAKAYAMA via GitGitGadget
@ 2026-08-11  6:35 ` Yoichi NAKAYAMA via GitGitGadget
  4 siblings, 0 replies; 18+ messages in thread
From: Yoichi NAKAYAMA via GitGitGadget @ 2026-08-11  6:35 UTC (permalink / raw)
  To: git
  Cc: Harald Nordgren, Yoichi Nakayama, D. Ben Knoble, Yoichi NAKAYAMA,
	Yoichi NAKAYAMA

From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>

When the user runs 'git worktree add ../foo-dir bar-topic' command
that does not exactly say which remote they want to work with, and
there is no local branch named bar-topic, we try to guess which remote
by passing bar-topic then create a new branch named bar-topic which
tracks the remote branch.

If there are multiple remotes that have branch named bar-topic, we
silently gave up, leaving the variable 'branch' intact.  Then we
entered the conditional clause 'if (!opts.orphan &&
!lookup_commit_reference_by_name(branch))' and triggered "invalid
reference" error.  This error message did not contain enough
information to resolve the issue where the remote could not be
guessed.

To improve the situation, we display a hint and a descriptive error
message and die immediately when multiple matching branches are found.

Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
---
    worktree add: improve message for ambiguous remote branch name

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2197%2Fyoichi%2Fimprove-worktree-add-error-message-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2197/yoichi/improve-worktree-add-error-message-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/2197

Range-diff vs v3:

 1:  1b9364da7e ! 1:  f7c413b588 worktree add: improve message for ambiguous remote branch name
     @@ Metadata
       ## Commit message ##
          worktree add: improve message for ambiguous remote branch name
      
     -    When the user runs 'git worktree add x y' command that does not
     -    exactly say which remote they want to work with, and there is no local
     -    branch named y, we try to guess which remote by passing y then create
     -    a new branch named y which tracks the remote branch.
     +    When the user runs 'git worktree add ../foo-dir bar-topic' command
     +    that does not exactly say which remote they want to work with, and
     +    there is no local branch named bar-topic, we try to guess which remote
     +    by passing bar-topic then create a new branch named bar-topic which
     +    tracks the remote branch.
      
     -    If there are multiple remotes that have branch named y, we silently
     -    gave up, leaving the variable branch intact.  This later causes
     -    creating local branch and worktree not happen, and we end up with
     -    passing an non-existing branch to lookup_commit_reference_by_name(),
     -    triggering "invalid reference" error and die.
     +    If there are multiple remotes that have branch named bar-topic, we
     +    silently gave up, leaving the variable 'branch' intact.  Then we
     +    entered the conditional clause 'if (!opts.orphan &&
     +    !lookup_commit_reference_by_name(branch))' and triggered "invalid
     +    reference" error.  This error message did not contain enough
     +    information to resolve the issue where the remote could not be
     +    guessed.
      
     -    To resolve this issue, display a hint and a descriptive error message
     -    and die immediately when multiple mathing branches are found.
     +    To improve the situation, we display a hint and a descriptive error
     +    message and die immediately when multiple matching branches are found.
      
          Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
      


 builtin/worktree.c      | 23 ++++++++++++++++++++++-
 t/t2400-worktree-add.sh |  4 ++--
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 654d27c3e1..b29c3a3755 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -64,6 +64,19 @@
 	"\n" \
 	"    git worktree add --orphan %s\n")
 
+#define WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT \
+	_("Matched multiple remote tracking branches, you can list them by:\n" \
+	"\n" \
+	"    git branch -r --list \"*/%s\"\n" \
+	"\n" \
+	"If you meant to create a worktree from a remote tracking branch on,\n" \
+	"e.g. 'origin', you can do so by:\n" \
+	"\n" \
+	"    git worktree add -b %s %s origin/%s\n" \
+	"\n" \
+	"If you'd like to always prefer some remote, e.g. 'origin',\n" \
+	"consider setting checkout.defaultRemote=origin in your config.")
+
 static const char * const git_worktree_usage[] = {
 	BUILTIN_WORKTREE_ADD_USAGE,
 	BUILTIN_WORKTREE_LIST_USAGE,
@@ -904,10 +917,18 @@ static int add(int ac, const char **av, const char *prefix,
 
 		commit = lookup_commit_reference_by_name(branch);
 		if (!commit) {
-			remote = unique_tracking_name(branch, &oid, NULL);
+			int num_matches = 0;
+			remote = unique_tracking_name(branch, &oid, &num_matches);
 			if (remote) {
 				new_branch = branch;
 				branch = new_branch_to_free = remote;
+			} else if (num_matches > 1) {
+				if (!opts.quiet)
+					advise_if_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
+							  WORKTREE_ADD_AMBIGUOUS_REMOTE_BRANCH_NAME_HINT_TEXT,
+							  branch, branch, path, branch);
+				die(_("'%s' matched multiple (%d) remote tracking branches"),
+				    branch, num_matches);
 			}
 		}
 
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 87b926728a..5c105cf252 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -624,12 +624,12 @@ test_expect_success '"add" <path> <branch> dwims' '
 test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' '
 	test_when_finished rm -rf repo_upstream repo_dwim foo &&
 	setup_remote_repo repo_upstream repo_dwim &&
-	git init repo_dwim &&
 	(
 		cd repo_dwim &&
 		git remote add repo_upstream2 ../repo_upstream &&
 		git fetch repo_upstream2 &&
-		test_must_fail git worktree add ../foo foo &&
+		test_must_fail git worktree add ../foo foo 2>error.actual &&
+		test_grep "matched multiple (2) remote tracking branches" error.actual &&
 		git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo &&
 		git status -uno --porcelain >status.actual &&
 		test_must_be_empty status.actual

base-commit: 010afd3166ddc64c9863b1506f12cbcdda0d4ea1
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2026-08-11  6:36 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-08  8:21 [PATCH] worktree add: improve message for ambiguous remote branch name Yoichi NAKAYAMA via GitGitGadget
2026-08-08 17:00 ` Junio C Hamano
2026-08-08 21:57   ` Junio C Hamano
2026-08-09  7:45     ` Harald Nordgren
2026-08-09 18:19       ` Junio C Hamano
2026-08-10 10:12         ` Harald Nordgren
2026-08-09 18:17     ` Junio C Hamano
2026-08-10 13:04     ` Yoichi Nakayama
2026-08-10 13:00   ` Yoichi Nakayama
2026-08-10 13:07 ` D. Ben Knoble
2026-08-10 13:35   ` Yoichi Nakayama
2026-08-10 15:06     ` Junio C Hamano
2026-08-10 21:36   ` Yoichi Nakayama
2026-08-10 15:07 ` [PATCH v2] " Yoichi NAKAYAMA via GitGitGadget
2026-08-10 20:55 ` [PATCH v3] " Yoichi NAKAYAMA via GitGitGadget
2026-08-11  0:03   ` Junio C Hamano
2026-08-11  6:31     ` Yoichi Nakayama
2026-08-11  6:35 ` [PATCH v4] " Yoichi NAKAYAMA via GitGitGadget

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.