Git development
 help / color / mirror / Atom feed
From: "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Harald Nordgren <haraldnordgren@gmail.com>,
	Harald Nordgren <haraldnordgren@gmail.com>
Subject: [PATCH 1/2] branch: suggest <remote>/<branch> on upstream slip
Date: Fri, 12 Jun 2026 11:10:18 +0000	[thread overview]
Message-ID: <21684539debaf433b6b63404e1a7622a5cc33283.1781262619.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2331.git.git.1781262619.gitgitgadget@gmail.com>

From: Harald Nordgren <haraldnordgren@gmail.com>

"git branch --set-upstream-to origin main" reads the trailing word as
the local branch to operate on and dies with "branch 'main' does not
exist", pointing at the wrong problem.

When that branch is missing and "<remote>/<branch>" names a real
remote-tracking ref, suggest the intended
"git branch --set-upstream-to=<remote>/<branch>" form.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
---
 builtin/branch.c  | 17 +++++++++++++++++
 t/t3200-branch.sh | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/builtin/branch.c b/builtin/branch.c
index 1572a4f9ef..7ad3efb908 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -957,6 +957,23 @@ int cmd_branch(int argc,
 		if (!refs_ref_exists(get_main_ref_store(the_repository), branch->refname)) {
 			if (!argc || branch_checked_out(branch->refname))
 				die(_("no commit on branch '%s' yet"), branch->name);
+			if (argc == 1 && !strchr(new_upstream, '/') &&
+			    remote_is_configured(remote_get(new_upstream), 0)) {
+				struct strbuf remote_ref = STRBUF_INIT;
+
+				strbuf_addf(&remote_ref, "refs/remotes/%s/%s",
+					    new_upstream, argv[0]);
+				if (refs_ref_exists(get_main_ref_store(the_repository),
+						    remote_ref.buf)) {
+					int code = die_message(_("--set-upstream-to takes a single <remote>/<branch> argument"));
+					advise_if_enabled(ADVICE_SET_UPSTREAM_FAILURE,
+							  _("Did you mean to use: git branch --set-upstream-to=%s/%s?"),
+							  new_upstream, argv[0]);
+					strbuf_release(&remote_ref);
+					exit(code);
+				}
+				strbuf_release(&remote_ref);
+			}
 			die(_("branch '%s' does not exist"), branch->name);
 		}
 
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index e7829c2c4b..e2682a83a0 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -1022,6 +1022,44 @@ test_expect_success '--set-upstream-to fails on a missing dst branch' '
 	test_cmp expect err
 '
 
+test_expect_success '--set-upstream-to suggests <remote>/<branch> on slip' '
+	test_when_finished "git remote remove slip-remote" &&
+	git remote add slip-remote . &&
+	git update-ref refs/remotes/slip-remote/slip-feature HEAD &&
+	test_must_fail git branch --set-upstream-to slip-remote slip-feature 2>err &&
+	test_grep "takes a single <remote>/<branch> argument" err &&
+	test_grep "hint: Did you mean to use: git branch --set-upstream-to=slip-remote/slip-feature?" err &&
+	test_must_fail git -c advice.setUpstreamFailure=false \
+		branch --set-upstream-to slip-remote slip-feature 2>err &&
+	test_grep ! "Did you mean" err
+'
+
+test_expect_success '--set-upstream-to does not suggest when no matching remote ref' '
+	test_when_finished "git remote remove slip-remote" &&
+	git remote add slip-remote . &&
+	test_must_fail git branch --set-upstream-to slip-remote no-such-branch 2>err &&
+	test_grep "branch ${SQ}no-such-branch${SQ} does not exist" err &&
+	test_grep ! "Did you mean" err
+'
+
+test_expect_success '--set-upstream-to to a local branch is not mistaken for a slip' '
+	git branch slip-local-upstream &&
+	git branch slip-local-target &&
+	git branch --set-upstream-to=slip-local-upstream slip-local-target 2>err &&
+	test_grep ! "Did you mean" err &&
+	echo refs/heads/slip-local-upstream >expect &&
+	git config branch.slip-local-target.merge >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--set-upstream-to slip suggestion keeps a slashed branch name' '
+	test_when_finished "git remote remove slip-remote" &&
+	git remote add slip-remote . &&
+	git update-ref refs/remotes/slip-remote/slip/feature HEAD &&
+	test_must_fail git branch --set-upstream-to slip-remote slip/feature 2>err &&
+	test_grep "hint: Did you mean to use: git branch --set-upstream-to=slip-remote/slip/feature?" err
+'
+
 test_expect_success '--set-upstream-to fails on a missing src branch' '
 	test_must_fail git branch --set-upstream-to does-not-exist main 2>err &&
 	test_grep "the requested upstream branch '"'"'does-not-exist'"'"' does not exist" err
-- 
gitgitgadget


  reply	other threads:[~2026-06-12 11:10 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-12 11:10 [PATCH 0/2] branch/push: suggest intended form when remote/branch slip given Harald Nordgren via GitGitGadget
2026-06-12 11:10 ` Harald Nordgren via GitGitGadget [this message]
2026-06-12 11:10 ` [PATCH 2/2] push: suggest <remote> <branch> for a slash slip Harald Nordgren via GitGitGadget

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=21684539debaf433b6b63404e1a7622a5cc33283.1781262619.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=haraldnordgren@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox