Thread (62 messages) flat view 62 messages, 5 authors, 11d ago
COOLING11d

[PATCH v4] worktree add: improve message for ambiguous remote branch name

From: Yoichi NAKAYAMA via GitGitGadget <hidden>
Date: 2026-08-11 06:36:02
Subsystem: the rest · Maintainer: Linus Torvalds

From: Yoichi NAKAYAMA <redacted>

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 <redacted>
---
    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 [off-list ref]
      


 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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help