worktree add: improve message for ambiguous remote branch name
When the user runs 'git worktree add ../foo-dir 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 silently gave up, leaving the variable 'branch' intact. We then entered the conditional clause 'if (!opts.orphan && !lookup_commit_reference_by_name(branch))' and triggered an "invalid reference" error. This error message did not provide enough information to resolve the ambiguity. When multiple matching branches are found, display a hint and a descriptive error message and die immediately. Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>next
parent
05cf4ceb5b
commit
85489606d8
|
|
@ -763,6 +763,25 @@ static int dwim_orphan(const struct add_opts *opts, int opt_track, int remote)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void advise_disambiguating_remotes(const char *path, const char *branch,
|
||||
const struct string_list *matched_remote_names)
|
||||
{
|
||||
struct string_list_item *item;
|
||||
|
||||
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 create a worktree from a remote tracking branch on\n"
|
||||
"<remote>, you can do so by:\n"
|
||||
"\n"
|
||||
" git worktree add -b %s %s <remote>/%s\n"
|
||||
"\n"
|
||||
"If you'd like to always prefer some remote, e.g. 'origin',\n"
|
||||
"consider setting checkout.defaultRemote=origin in your config."),
|
||||
branch, path, branch);
|
||||
}
|
||||
|
||||
static char *dwim_branch(const char *path, char **new_branch)
|
||||
{
|
||||
int n;
|
||||
|
|
@ -897,17 +916,29 @@ static int add(int ac, const char **av, const char *prefix,
|
|||
/* DWIM: Infer --orphan when repo has no refs. */
|
||||
opts.orphan = (!s) && dwim_orphan(&opts, !!opt_track, 1);
|
||||
} else if (ac == 2) {
|
||||
struct object_id oid;
|
||||
struct commit *commit;
|
||||
char *remote;
|
||||
|
||||
commit = lookup_commit_reference_by_name(branch);
|
||||
if (!commit) {
|
||||
remote = unique_tracking_name(branch, &oid, NULL, NULL);
|
||||
struct object_id oid;
|
||||
char *remote;
|
||||
int num_matches = 0;
|
||||
struct string_list matched_remote_names = STRING_LIST_INIT_DUP;
|
||||
|
||||
remote = unique_tracking_name(branch, &oid, &num_matches,
|
||||
&matched_remote_names);
|
||||
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_disambiguating_remotes(path, branch,
|
||||
&matched_remote_names);
|
||||
die(_("'%s' matched multiple (%d) remote tracking branches"),
|
||||
branch, num_matches);
|
||||
}
|
||||
string_list_clear(&matched_remote_names, 0);
|
||||
}
|
||||
|
||||
if (!strcmp(branch, "HEAD"))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue