Subject: Re: Remote tracking option hint for git-switch still shows git-checkout command

From: Junio C Hamano <[email-masked]>
Date: Tue, 27 Jan 2026 08:29:33 -0800

Simon Cheng <[email-masked]> writes:

> When `git-switch my-branch` is unable to guess a unique remote
> tracking branch, the shown hint still displays an example with the
> `git-checkout` command.
>
> ❯ git switch my-branch
> hint: If you meant to check out a remote tracking branch on, e.g. 'origin',
> hint: you can do so by fully qualifying the name with the --track option:
> hint:
> hint:     git checkout --track origin/<name>
> hint:
> hint: If you'd like to always have checkouts of an ambiguous <name> prefer
> hint: one remote, e.g. the 'origin' remote, consider setting
> hint: checkout.defaultRemote=origin in your config.
> fatal: 'my-branch' matched multiple (2) remote tracking branches
>
> Of course that works too, but it keeps the user guessing whether the
> `--track` option also exists for `git-switch`. Not to mention that
> `git-checkout` is now largely superseded by `git-switch` and
> `git-restore` and is no longer recommended, as far as I understand it.
>
> So I think it makes sense to either:
> 1. make the recommended command match the one ran by the user, or
> 2. always recommend `git-switch` as opposed to `git-checkout`

Here is what I did while waiting for -rc2 to pass my local tests,
which is unfinished, but it would be a good start.  What missing are

(1) get rid of the usagestr[] parameter from checkout_main(), move
    the usage strings for these three commands into the function
    scope of checkout_main(), and choose among them based on the
    value of which_command parameter;

(2) tests.

We are not deprecating checkout in any way, so #1 is far more
preferrable than #2.

 builtin/checkout.c | 40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git c/builtin/checkout.c w/builtin/checkout.c
index 0ba4f03f2e..4d0e70ea15 100644
--- c/builtin/checkout.c
+++ w/builtin/checkout.c
@@ -1293,9 +1293,17 @@ static void setup_new_branch_info_and_source_tree(
 	}
 }
 
+
+enum checkout_switch {
+	CHECKOUT_CHECKOUT = 1,
+	CHECKOUT_SWITCH = 2,
+	CHECKOUT_RESTORE = 3,
+};
+
 static char *parse_remote_branch(const char *arg,
 				 struct object_id *rev,
-				 int could_be_checkout_paths)
+				 int could_be_checkout_paths,
+				 enum checkout_switch which_command)
 {
 	int num_matches = 0;
 	char *remote = unique_tracking_name(arg, rev, &num_matches);
@@ -1308,14 +1316,30 @@ 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 checkout --track origin/<name>\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."));
+			     "checkout.defaultRemote=origin in your config."),
+			   cmdname);
 	    }
 
 	    die(_("'%s' matched multiple (%d) remote tracking branches"),
@@ -1327,6 +1351,7 @@ static char *parse_remote_branch(const char *arg,
 
 static int parse_branchname_arg(int argc, const char **argv,
 				int dwim_new_local_branch_ok,
+				enum checkout_switch which_command,
 				struct branch_info *new_branch_info,
 				struct checkout_opts *opts,
 				struct object_id *rev)
@@ -1436,7 +1461,8 @@ static int parse_branchname_arg(int argc, const char **argv,
 
 		if (recover_with_dwim) {
 			remote = parse_remote_branch(arg, rev,
-						     could_be_checkout_paths);
+						     could_be_checkout_paths,
+						     which_command);
 			if (remote) {
 				*new_branch = arg;
 				arg = remote;
@@ -1767,6 +1793,7 @@ static char cb_option = 'b';
 
 static int checkout_main(int argc, const char **argv, const char *prefix,
 			 struct checkout_opts *opts, struct option *options,
+			 enum checkout_switch which_command,
 			 const char * const usagestr[])
 {
 	int parseopt_flags = 0;
@@ -1893,7 +1920,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			opts->dwim_new_local_branch &&
 			opts->track == BRANCH_TRACK_UNSPECIFIED &&
 			!opts->new_branch;
-		int n = parse_branchname_arg(argc, argv, dwim_ok,
+		int n = parse_branchname_arg(argc, argv, dwim_ok, which_command,
 					     &new_branch_info, opts, &rev);
 		argv += n;
 		argc -= n;
@@ -2032,6 +2059,7 @@ int cmd_checkout(int argc,
 	options = add_checkout_path_options(&opts, options);
 
 	return checkout_main(argc, argv, prefix, &opts, options,
+			     CHECKOUT_CHECKOUT,
 			     checkout_usage);
 }
 
@@ -2071,6 +2099,7 @@ int cmd_switch(int argc,
 	cb_option = 'c';
 
 	return checkout_main(argc, argv, prefix, &opts, options,
+			     CHECKOUT_SWITCH,
 			     switch_branch_usage);
 }
 
@@ -2107,5 +2136,6 @@ int cmd_restore(int argc,
 	options = add_checkout_path_options(&opts, options);
 
 	return checkout_main(argc, argv, prefix, &opts, options,
+			     CHECKOUT_RESTORE,
 			     restore_usage);
 }