checkout: improve message for ambiguous remote branch name
When the user runs 'git checkout bar-topic' without specifying a remote, and there is no local branch named bar-topic, we try to guess which remote branch bar-topic refers to, then create a new branch named bar-topic that tracks the remote branch. If multiple remotes have a branch named bar-topic, we cannot determine a single remote. To make it easier to resolve the ambiguity, provide the names of the matching remotes for the specified branch name. To achieve that, add an optional feature to the `unique_tracking_name()` function that allows the matching remote names to be exposed to the caller. Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>next
parent
1af4c26d69
commit
05cf4ceb5b
|
|
@ -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 <remote>,\n"
|
||||
"you can do so by fully qualifying the name with the --track option:\n"
|
||||
"\n"
|
||||
" git %s --track origin/<name>\n"
|
||||
" git %s --track <remote>/%s\n"
|
||||
"\n"
|
||||
"If you'd like to always have checkouts of an ambiguous <name> 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
13
checkout.c
13
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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue