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

Re: [PATCH 2/2] push: add an advice on unqualified <dst> push

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Oct 10, 2018, 21:23 UTC
Message-ID
<87r2gxebsi.fsf@evledraar.gmail.com>
In-Reply-To
<20181010205505.GB12949@sigill.intra.peff.net>
On Wed, Oct 10 2018, Jeff King wrote:
Show 52 quoted lines
> On Wed, Oct 10, 2018 at 10:41:45AM +0000, Ævar Arnfjörð Bjarmason wrote:
>
>> Improve the error message added in f8aae12034 ("push: allow
>> unqualified dest refspecs to DWIM", 2008-04-23), which before this
>> change looks like this:
>>
>>     $ git push avar v2.19.0^{commit}:newbranch -n
>>     error: unable to push to unqualified destination: newbranch
>>     The destination refspec neither matches an existing ref on the remote nor
>>     begins with refs/, and we are unable to guess a prefix based on the source ref.
>>     error: failed to push some refs to 'git@github.com:avar/git.git'
>
> Thanks for looking into this. Despite being largely responsible for that
> message myself, I always cringe when I see it because it's so opaque.
>
>> This message needed to be read very carefully to spot how to fix the
>> error, i.e. to push to refs/heads/newbranch, and it didn't use the
>> advice system (since initial addition of the error predated it).
>>
>> Fix both of those, now the message will look like this instead:
>>
>>     $ ./git-push avar v2.19.0^{commit}:newbranch -n
>>     error: unable to push to unqualified destination: newbranch
>>     hint: The destination refspec neither matches an existing
>>     hint: ref on the remote nor begins with refs/, and we are
>>     hint: unable to guess a prefix based on the source ref.
>>     hint:
>>     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.
>
> This is much better, and I love the customized behavior based on the
> object type.
>
> I wonder if we could reword the first paragraph to be a little less
> confusing, and spell out what we tried already. E.g., something like:
>
>   The destination you provided is not a full refname (i.e., starting
>   with "ref"). Git tried to guess what you meant by:
>
>     - looking for a matching branch or tag on the remote side
>
>     - looking at the refname of the local source
>
>   but neither worked.
>
>   The <src> part of the refspec is a commit object.
>   Did you mean...

Yeah that makes sense. I was trying to avoid touching the existing wording to make this more surgical, but you came up with it, and since you don't like it I'll just change that too.

Show 18 quoted lines
> I'm not sure about saying "branch or tag" in the first bullet. It's
> friendlier to most users, but less technically correct (if you said
> "notes/foo", I believe we'd match an existing "refs/notes/foo", because
> it's really just using the normal lookup rules).
>
> Also, as an aside, I wonder if we should allow "heads/foo" to work as
> "refs/heads/foo" (even when no such ref already exists). But that is
> totally orthogonal to changing the message.
>
>> The if/else duplication for all of OBJ_{COMMIT,TAG,TREE,BLOB} is
>> unfortunate, but is required to correctly mark the messages for
>> translation.
>
> I think it would probably be OK to put the first paragraph in its own
> variable. I know we try to avoid translation lego, but I'd think
> paragraphs are separate units. Or are you worried about how to get them
> into the same advise() call? I don't know that we need to, but we could
> also plug one into the other with a "%s" (and leave a translator note).

To be honest from being on the code side of a much bigger i18n effort (the MediaWiki/WikiMedia software) back in the early days of my career I just do this sort of thing reflexively, because from experience when I started trying to simplify stuff by making assumptions I was wrong every time.

Although in that case there were >100+ languages, so maybe we can get away with this.

In this case one red flag I see is that we make a reference to "the source ref" in the first paragraph, and then in the second we'll either talk about "commit", "tag" or "blob" etc. Now imagine a language where those words have different genders, and where even secondary references to those things ("the source ref") spill over and need to be changed too.

You also get languages where a message that stretches multiple paragraphs flows more naturally if the wording is re-arranged, even between paragraphs. This is why document translation systems generally split things by sections at best (not paragraphs), or just by whole documents.

Show 23 quoted lines
>> diff --git a/Documentation/config.txt b/Documentation/config.txt
>> index 1546833213..fd455e2739 100644
>> --- a/Documentation/config.txt
>> +++ b/Documentation/config.txt
>> @@ -320,6 +320,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.
>> +	pushAmbigiousRefName::
>> +		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.
>
> I guess you could argue that this is "ambiguous", but usually we'd use
> that term to mean "there were two branches that matched on the other
> side". But here it's actually "no branches matched" (actually, it makes
> me wonder what we'd do pushing "foo" when that name is ambiguous on the
> other side).
>
> So I wonder if this ought to be pushUnqualifiedRefname or something.
Yeah that sounds better. Will change it.
Show 35 quoted lines
>> @@ -1046,13 +1047,60 @@ static int match_explicit(struct ref *src, struct ref *dst,
>>  		else if ((dst_guess = guess_ref(dst_value, matched_src))) {
>>  			matched_dst = make_linked_ref(dst_guess, dst_tail);
>>  			free(dst_guess);
>> -		} else
>> -			error(_("unable to push to unqualified destination: %s\n"
>> -				"The destination refspec neither matches an "
>> -				"existing ref on the remote nor\n"
>> -				"begins with refs/, and we are unable to "
>> -				"guess a prefix based on the source ref."),
>> -			      dst_value);
>> +		} else {
>> +			struct object_id oid;
>> +			enum object_type type;
>> +
>> +			error("unable to push to unqualified destination: %s", dst_value);
>> +			if (!advice_push_ambiguous_ref_name)
>> +				break;
>
> This break feels funny, because it controls flow much larger than this
> if/else. It does the right thing now, but it must remain in sync with
> what comes at the end of that long string of advise() messages.
>
> Can we just do it as:
>
>   if (advice_push_ambiguous_ref_name) {
> 	struct object_id oid;
> 	enum object_type type;
>
> 	if (get_oid(...))
> 	   etc...
>   }
>
> instead? That pushes your indentation one level in, but I think the
> whole conditional body might be cleaner in a helper function anyway.

I started out with that and found myself really constrained by the 72 char ceiling which I'm already smashing through with these ~95 character lines (but at least it's under 100!). But sure, we can do with 8 more.

Previous: Jeff KingNext: Jeff King
Message 6 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.