git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4 5/7] push: add an advice on unqualified <dst> push

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Nov 13, 2018, 19:52 UTC
Message-ID
<20181113195245.14296-6-avarab@gmail.com>
In-Reply-To
<20181026230741.23321-1-avarab@gmail.com>

Add an advice to the recently improved error message added in f8aae12034 ("push: allow unqualified dest refspecs to DWIM", 2008-04-23).

Now with advice.pushUnqualifiedRefName=true (on by default) we show a hint about how to proceed:

    $ ./git-push avar v2.19.0^{commit}:newbranch -n
    error: The destination you provided is not a full refname (i.e.,
    starting with "refs/"). We tried to guess what you meant by:
    - Looking for a ref that matches 'newbranch' on the remote side.
    - Checking if the <src> being pushed ('v2.19.0^{commit}')
      is a ref in "refs/{heads,tags}/". If so we add a corresponding
      refs/{heads,tags}/ prefix on the remote side.
    Neither worked, so we gave up. You must fully qualify the ref.
    hint: The <src> part of the refspec is a commit object.
    hint: Did you mean to create a new branch by pushing to
    hint: 'v2.19.0^{commit}:refs/heads/newbranch'?
    error: failed to push some refs to 'git@github.com:avar/git.git'

When trying to push a tag, tree or a blob we suggest that perhaps the user meant to push them to refs/tags/ instead.

The if/else duplication for all of OBJ_{COMMIT,TAG,TREE,BLOB} is unfortunate, but is required to correctly mark the messages for translation. See the discussion in <87r2gxebsi.fsf@evledraar.gmail.com> about that.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/config/advice.txt |  7 +++++++
 advice.c                        |  2 ++
 advice.h                        |  1 +
 remote.c                        | 37 +++++++++++++++++++++++++++++++++
 t/t5505-remote.sh               | 28 +++++++++++++++++++++++++
 5 files changed, 75 insertions(+)
diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt
index 57fcd4c862..88620429ea 100644
--- a/Documentation/config/advice.txt
+++ b/Documentation/config/advice.txt
@@ -30,6 +30,13 @@ advice.*::
 		tries to overwrite a remote ref that points at an
 		object that is not a commit-ish, or make the remote
 		ref point at an object that is not a commit-ish.
+	pushUnqualifiedRefname::
+		Shown when linkgit:git-push[1] gives up trying to
+		guess based on the source and destination refs what
+		remote ref namespace the source belongs in, but where
+		we can still suggest that the user push to either
+		refs/heads/* or refs/tags/* based on the type of the
+		source object.
 	statusHints::
 		Show directions on how to proceed from the current
 		state in the output of linkgit:git-status[1], in
diff --git a/advice.c b/advice.c
index 5f35656409..567209aa79 100644
--- a/advice.c
+++ b/advice.c
@@ -9,6 +9,7 @@ int advice_push_non_ff_matching = 1;
 int advice_push_already_exists = 1;
 int advice_push_fetch_first = 1;
 int advice_push_needs_force = 1;
+int advice_push_unqualified_ref_name = 1;
 int advice_status_hints = 1;
 int advice_status_u_option = 1;
 int advice_commit_before_merge = 1;
@@ -63,6 +64,7 @@ static struct {
 	{ "pushAlreadyExists", &advice_push_already_exists },
 	{ "pushFetchFirst", &advice_push_fetch_first },
 	{ "pushNeedsForce", &advice_push_needs_force },
+	{ "pushUnqualifiedRefName", &advice_push_unqualified_ref_name },
 	{ "statusHints", &advice_status_hints },
 	{ "statusUoption", &advice_status_u_option },
 	{ "commitBeforeMerge", &advice_commit_before_merge },
diff --git a/advice.h b/advice.h
index 696bf0e7d2..f875f8cd8d 100644
--- a/advice.h
+++ b/advice.h
@@ -9,6 +9,7 @@ extern int advice_push_non_ff_matching;
 extern int advice_push_already_exists;
 extern int advice_push_fetch_first;
 extern int advice_push_needs_force;
+extern int advice_push_unqualified_ref_name;
 extern int advice_status_hints;
 extern int advice_status_u_option;
 extern int advice_commit_before_merge;
diff --git a/remote.c b/remote.c
index ba8abf4d32..f7477b8eb6 100644
--- a/remote.c
+++ b/remote.c
@@ -13,6 +13,7 @@
 #include "mergesort.h"
 #include "argv-array.h"
 #include "commit-reach.h"
+#include "advice.h"
 
 enum map_direction { FROM_SRC, FROM_DST };
 
@@ -1008,6 +1009,9 @@ static int match_explicit_lhs(struct ref *src,
 static void show_push_unqualified_ref_name_error(const char *dst_value,
 						 const char *matched_src_name)
 {
+	struct object_id oid;
+	enum object_type type;
+
 	/*
 	 * TRANSLATORS: "matches '%s'%" is the <dst> part of "git push
 	 * <remote> <src>:<dst>" push, and "being pushed ('%s')" is
@@ -1023,6 +1027,39 @@ static void show_push_unqualified_ref_name_error(const char *dst_value,
 		"\n"
 		"Neither worked, so we gave up. You must fully qualify the ref."),
 	      dst_value, matched_src_name);
+
+	if (!advice_push_unqualified_ref_name)
+		return;
+
+	if (get_oid(matched_src_name, &oid))
+		BUG("'%s' is not a valid object, "
+		    "match_explicit_lhs() should catch this!",
+		    matched_src_name);
+	type = oid_object_info(the_repository, &oid, NULL);
+	if (type == OBJ_COMMIT) {
+		advise(_("The <src> part of the refspec is a commit object.\n"
+			 "Did you mean to create a new branch by pushing to\n"
+			 "'%s:refs/heads/%s'?"),
+		       matched_src_name, dst_value);
+	} else if (type == OBJ_TAG) {
+		advise(_("The <src> part of the refspec is a tag object.\n"
+			 "Did you mean to create a new tag by pushing to\n"
+			 "'%s:refs/tags/%s'?"),
+		       matched_src_name, dst_value);
+	} else if (type == OBJ_TREE) {
+		advise(_("The <src> part of the refspec is a tree object.\n"
+			 "Did you mean to tag a new tree by pushing to\n"
+			 "'%s:refs/tags/%s'?"),
+		       matched_src_name, dst_value);
+	} else if (type == OBJ_BLOB) {
+		advise(_("The <src> part of the refspec is a blob object.\n"
+			 "Did you mean to tag a new blob by pushing to\n"
+			 "'%s:refs/tags/%s'?"),
+		       matched_src_name, dst_value);
+	} else {
+		BUG("'%s' should be commit/tag/tree/blob, is '%d'",
+		    matched_src_name, type);
+	}
 }
 
 static int match_explicit(struct ref *src, struct ref *dst,
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index d2a2cdd453..f069cbcc24 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -1222,4 +1222,32 @@ test_expect_success 'add remote matching the "insteadOf" URL' '
 	git remote add backup xyz@example.com
 '
 
+test_expect_success 'unqualified <dst> refspec DWIM and advice' '
+	test_when_finished "(cd test && git tag -d some-tag)" &&
+	(
+		cd test &&
+		git tag -a -m "Some tag" some-tag master &&
+		exit_with=true &&
+		for type in commit tag tree blob
+		do
+			if test "$type" = "blob"
+			then
+				oid=$(git rev-parse some-tag:file)
+			else
+				oid=$(git rev-parse some-tag^{$type})
+			fi &&
+			test_must_fail git push origin $oid:dst 2>err &&
+			test_i18ngrep "error: The destination you" err &&
+			test_i18ngrep "hint: Did you mean" err &&
+			test_must_fail git -c advice.pushUnqualifiedRefName=false \
+				push origin $oid:dst 2>err &&
+			test_i18ngrep "error: The destination you" err &&
+			test_i18ngrep ! "hint: Did you mean" err ||
+			exit_with=false
+		done &&
+		$exit_with
+	)
+'
+
+
 test_done
-- 
2.19.1.1182.g4ecb1133ce
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 21 of 53 in “add an advice on unqualified <dst> push”
  1. 0/2 add an advice on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 10, 2018
  2. 1/2 i18n: remote.c: mark error(...) messages for translationÆvar Arnfjörð Bjarmason, Oct 10, 2018
  3. Jeff KingOct 10, 2018
  4. 2/2 push: add an advice on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 10, 2018
  5. Jeff KingOct 10, 2018
  6. Ævar Arnfjörð BjarmasonOct 10, 2018
  7. Jeff KingOct 11, 2018
  8. Junio C HamanoOct 11, 2018
  9. Ævar Arnfjörð BjarmasonOct 26, 2018
  10. Junio C HamanoOct 29, 2018
  11. Junio C HamanoOct 29, 2018
  12. 0/7 fixes for unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 26, 2018
  13. 0/8 fixes for unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 26, 2018
  14. Jeff KingNov 2, 2018
  15. 0/7 fixes for unqualified <dst> pushÆvar Arnfjörð Bjarmason, Nov 13, 2018
  16. Junio C HamanoNov 14, 2018
  17. 1/7 remote.c: add braces in anticipation of a follow-up changeÆvar Arnfjörð Bjarmason, Nov 13, 2018
  18. 2/7 i18n: remote.c: mark error(...) messages for translationÆvar Arnfjörð Bjarmason, Nov 13, 2018
  19. 3/7 push: improve the error shown on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Nov 13, 2018
  20. 4/7 push: move unqualified refname error into a functionÆvar Arnfjörð Bjarmason, Nov 13, 2018
  21. 5/7 push: add an advice on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Nov 13, 2018
  22. 6/7 push: test that <src> doesn't DWYM if <dst> is unqualifiedÆvar Arnfjörð Bjarmason, Nov 13, 2018
  23. 7/7 push doc: document the DWYM behavior pushing to unqualified <dst>Ævar Arnfjörð Bjarmason, Nov 13, 2018
  24. 1/8 remote.c: add braces in anticipation of a follow-up changeÆvar Arnfjörð Bjarmason, Oct 26, 2018
  25. 2/8 i18n: remote.c: mark error(...) messages for translationÆvar Arnfjörð Bjarmason, Oct 26, 2018
  26. 3/8 push: improve the error shown on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 26, 2018
  27. Junio C HamanoOct 29, 2018
  28. 4/8 push: move unqualified refname error into a functionÆvar Arnfjörð Bjarmason, Oct 26, 2018
  29. 6/8 push: test that <src> doesn't DWYM if <dst> is unqualifiedÆvar Arnfjörð Bjarmason, Oct 26, 2018
  30. Junio C HamanoOct 29, 2018
  31. 5/8 push: add an advice on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 26, 2018
  32. Junio C HamanoOct 29, 2018
  33. Jeff KingNov 2, 2018
  34. 7/8 push: add DWYM support for "git push refs/remotes/...:<dst>"Ævar Arnfjörð Bjarmason, Oct 26, 2018
  35. Junio C HamanoOct 29, 2018
  36. Ævar Arnfjörð BjarmasonOct 29, 2018
  37. Junio C HamanoNov 1, 2018
  38. Ævar Arnfjörð BjarmasonNov 5, 2018
  39. Junio C HamanoNov 5, 2018
  40. Junio C HamanoOct 29, 2018
  41. Junio C HamanoOct 29, 2018
  42. Ævar Arnfjörð BjarmasonOct 29, 2018
  43. 8/8 push doc: document the DWYM behavior pushing to unqualified <dst>Ævar Arnfjörð Bjarmason, Oct 26, 2018
  44. 1/7 remote.c: add braces in anticipation of a follow-up changeÆvar Arnfjörð Bjarmason, Oct 26, 2018
  45. Stefan BellerOct 26, 2018
  46. 2/7 i18n: remote.c: mark error(...) messages for translationÆvar Arnfjörð Bjarmason, Oct 26, 2018
  47. 3/7 push: improve the error shown on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 26, 2018
  48. 5/7 push: add an advice on unqualified <dst> pushÆvar Arnfjörð Bjarmason, Oct 26, 2018
  49. 6/7 push: test that <src> doesn't DWYM if <dst> is unqualifiedÆvar Arnfjörð Bjarmason, Oct 26, 2018
  50. 7/7 push: add DWYM support for "git push refs/remotes/...:<dst>"Ævar Arnfjörð Bjarmason, Oct 26, 2018
  51. 4/7 push: move unqualified refname error into a functionÆvar Arnfjörð Bjarmason, Oct 26, 2018
  52. Junio C HamanoOct 10, 2018
  53. Jeff KingOct 11, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.