Re: [PATCH v5 1/2] checkout: improve message for ambiguous remote branch name
- From
D. Ben Knoble <ben.knoble@gmail.com>
- Date
- Aug 19, 2026, 22:54 UTC
- Message-ID
- <CALnO6CCQppTnw1Y-6ibmcko0dM3hy8riPanD9BNyb+MW8a5nAw@mail.gmail.com>
- In-Reply-To
- <b838fdabb7cd0d044294d54fd30cb51f040505ad.1787143859.git.gitgitgadget@gmail.com>
On Wed, Aug 19, 2026 at 8:51 AM Yoichi NAKAYAMA via GitGitGadget <gitgitgadget@gmail.com> wrote:
Show 37 quoted lines
>
> From: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
>
> When the user runs 'git checkout 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 multiple remotes have a branch named bar-topic, we cannot determine
> a single specific remote. Therefore, we provide information that the
> user can utilize to resolve the issue.
>
> To make the advice more feasible, we will provide matched remote names
> for the specified branch name.
>
> To achive that, we add an optional feature to the
> `unique_tracking_name()` function that allows the matched remote name
> to be exposed to the caller.
>
> Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
> ---
> builtin/checkout.c | 75 +++++++++++++++++++++++++++-------------------
> builtin/worktree.c | 4 +--
> checkout.c | 14 +++++++--
> checkout.h | 5 +++-
> 4 files changed, 63 insertions(+), 35 deletions(-)
>
> diff --git a/builtin/checkout.c b/builtin/checkout.c
> index 55e3a89a85..a2749352e6 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -1343,13 +1343,51 @@ enum checkout_command {
> CHECKOUT_RESTORE = 3,
> };
>
> +static void be_explicit(const char *branch,Be explicit about what? Reading below, a better name might be "advise_ambiguous_remote_branch_name" or something, idk.
Show 34 quoted lines
> + enum checkout_command which_command,
> + const struct string_list *matched_remote_names)
> +{
> + const char *cmdname;
> + struct string_list_item *item;
> +
> + switch (which_command) {
> + case CHECKOUT_CHECKOUT:
> + cmdname = "checkout";
> + break;
> + case CHECKOUT_SWITCH:
> + cmdname = "switch";
> + break;
> + default:
> + BUG("command <%d> should not reach parse_remote_branch",
> + which_command);
> + break;
> + }
> +
> + advise(_("Branches with the same name appears in multiple remotes:"));
> + for_each_string_list_item(item, matched_remote_names) {
> + advise(_(" %s"), item->string);
> + }
> + advise(_("If you meant to check out a remote tracking branch on <remote>,\n"
> + "you can do so by fully qualifying the name with the --track option:\n"
> + "\n"
> + " git %s --track <remote>/%s\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."),
> + cmdname, branch);
> +}
> +I think it's possible this refactor is a bit distracting from the overall goal of the patch, though I don't think extracting the function is a bad thing. Maybe split the steps up into
- mechanical refactoring (no behavior change) - changes to improve the message (easier to see the diff)
? Just my 2 cents.
Show 57 quoted lines
> static char *parse_remote_branch(const char *arg,
> struct object_id *rev,
> int could_be_checkout_paths,
> enum checkout_command which_command)
> {
> int num_matches = 0;
> - char *remote = unique_tracking_name(arg, rev, &num_matches);
> + struct string_list matched_remote_names = STRING_LIST_INIT_DUP;
> +
> + char *remote = unique_tracking_name(arg, rev, &num_matches,
> + &matched_remote_names);
>
> if (remote && could_be_checkout_paths) {
> die(_("'%s' could be both a local file and a tracking branch.\n"
> @@ -1358,37 +1396,14 @@ static char *parse_remote_branch(const char *arg,
> }
>
> if (!remote && num_matches > 1) {
> - if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) {
> - const char *cmdname;
> -
> - switch (which_command) {
> - case CHECKOUT_CHECKOUT:
> - cmdname = "checkout";
> - break;
> - case CHECKOUT_SWITCH:
> - cmdname = "switch";
> - break;
> - default:
> - BUG("command <%d> should not reach parse_remote_branch",
> - which_command);
> - break;
> - }
> -
> - advise(_("If you meant to check out a remote tracking branch on, e.g. 'origin',\n"
> - "you can do so by fully qualifying the name with the --track option:\n"
> - "\n"
> - " git %s --track 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."),
> - cmdname);
> - }
> -
> - die(_("'%s' matched multiple (%d) remote tracking branches"),
> - arg, num_matches);
> + if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME))
> + be_explicit(arg, which_command, &matched_remote_names);
> + die(_("'%s' matched multiple (%d) remote tracking branches"),
> + arg, num_matches);
> }
>
> + string_list_clear(&matched_remote_names, 0);
> +
> return remote;
> }[rest of diff snipped]