diff --git a/builtin/checkout.c b/builtin/checkout.c index 0065458aa3..b2fc0bbb1a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1340,9 +1340,12 @@ enum checkout_command { CHECKOUT_RESTORE = 3, }; -static void advise_disambiguating_remotes(enum checkout_command which_command) +static void advise_disambiguating_remotes(enum checkout_command which_command, + const char *branch, + const struct string_list *matched_remote_names) { const char *cmdname; + struct string_list_item *item; switch (which_command) { case CHECKOUT_CHECKOUT: @@ -1357,15 +1360,19 @@ static void advise_disambiguating_remotes(enum checkout_command which_command) break; } - advise(_("If you meant to check out a remote tracking branch on, e.g. 'origin',\n" + advise(_("Branch name '%s' appears in multiple remotes:"), branch); + 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 ,\n" "you can do so by fully qualifying the name with the --track option:\n" "\n" - " git %s --track origin/\n" + " git %s --track /%s\n" "\n" - "If you'd like to always have checkouts of an ambiguous prefer\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); + cmdname, branch); } static char *parse_remote_branch(const char *arg, @@ -1374,7 +1381,10 @@ static char *parse_remote_branch(const char *arg, 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" @@ -1384,12 +1394,14 @@ static char *parse_remote_branch(const char *arg, if (!remote && num_matches > 1) { if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) - advise_disambiguating_remotes(which_command); - + advise_disambiguating_remotes(which_command, arg, + &matched_remote_names); die(_("'%s' matched multiple (%d) remote tracking branches"), arg, num_matches); } + string_list_clear(&matched_remote_names, 0); + return remote; } diff --git a/builtin/worktree.c b/builtin/worktree.c index d21c43fde3..590482e186 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -781,7 +781,7 @@ static char *dwim_branch(const char *path, char **new_branch) *new_branch = branchname; if (guess_remote) { struct object_id oid; - char *remote = unique_tracking_name(*new_branch, &oid, NULL); + char *remote = unique_tracking_name(*new_branch, &oid, NULL, NULL); return remote; } return NULL; @@ -903,7 +903,7 @@ 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); + remote = unique_tracking_name(branch, &oid, NULL, NULL); if (remote) { new_branch = branch; branch = new_branch_to_free = remote; diff --git a/checkout.c b/checkout.c index 1588b116ee..a0d0229435 100644 --- a/checkout.c +++ b/checkout.c @@ -8,6 +8,7 @@ #include "checkout.h" #include "config.h" #include "strbuf.h" +#include "string-list.h" struct tracking_name_data { /* const */ char *src_ref; @@ -17,6 +18,7 @@ struct tracking_name_data { const char *default_remote; char *default_dst_ref; struct object_id *default_dst_oid; + struct string_list *remote_names; }; #define TRACKING_NAME_DATA_INIT { 0 } @@ -39,6 +41,8 @@ static int check_tracking_name(struct remote *remote, void *cb_data) oidcpy(dst, cb->dst_oid); cb->default_dst_oid = dst; } + if (cb->remote_names) + string_list_append(cb->remote_names, remote->name); if (cb->dst_ref) { free(query.dst); return 0; @@ -48,14 +52,19 @@ static int check_tracking_name(struct remote *remote, void *cb_data) } char *unique_tracking_name(const char *name, struct object_id *oid, - int *dwim_remotes_matched) + int *dwim_remotes_matched, + struct string_list *dwim_remote_names) { struct tracking_name_data cb_data = TRACKING_NAME_DATA_INIT; const char *default_remote = NULL; - if (!repo_config_get_string_tmp(the_repository, "checkout.defaultremote", &default_remote)) + + if (!repo_config_get_string_tmp(the_repository, + "checkout.defaultremote", + &default_remote)) cb_data.default_remote = default_remote; cb_data.src_ref = xstrfmt("refs/heads/%s", name); cb_data.dst_oid = oid; + cb_data.remote_names = dwim_remote_names; for_each_remote(check_tracking_name, &cb_data); if (dwim_remotes_matched) *dwim_remotes_matched = cb_data.num_matches; diff --git a/checkout.h b/checkout.h index 55920e7aeb..0b185a0fc9 100644 --- a/checkout.h +++ b/checkout.h @@ -3,6 +3,8 @@ #include "hash.h" +struct string_list; + /* * Check if the branch name uniquely matches a branch name on a remote * tracking branch. Return the name of the remote if such a branch @@ -10,6 +12,7 @@ */ char *unique_tracking_name(const char *name, struct object_id *oid, - int *dwim_remotes_matched); + int *dwim_remotes_matched, + struct string_list *dwim_remote_names); #endif /* CHECKOUT_H */