user3423907
user3423907

Reputation:

git pushing commit shows error: unable to push to unqualified destination

I'm trying to push head commit to remote with WIP- showing error like

$ git push remote 51447424149c671958a2f76ec1fefb135a5c2cea:WIP-51447424149c671958a2f76ec1fefb135a5c2cea

[which results in]

error: unable to push to unqualified destination: WIP-51447424149c671958a2f76ec1fefb135a5c2cea
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 'https://github.com/abc'

Any help ?

Upvotes: 18

Views: 24456

Answers (2)

VonC
VonC

Reputation: 1326992

Git 2.21 (Q1 2019, 1 year later) will improve that error message: "git push $there $src:$dst" rejects when $dst is not a fully qualified refname and not clear what the end user meant.

The codepath has been taught to give a clearer error message, and also guess where the push should go by taking the type of the pushed object into account (e.g. a tag object would want to go under refs/tags/).

Note: DWIM (used below) is "do what I mean":

computer systems attempt to anticipate what users intend to do, correcting trivial errors automatically rather than blindly executing users' explicit but potentially incorrect inputs.

See commit 2219c09, commit bf70636, commit dd8dd30, commit 04d1728, commit c83cca3, commit 8b0e542, commit cab5398 (13 Nov 2018) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano -- gitster -- in commit 0a84724, 04 Jan 2019)

push: improve the error shown on unqualified <dst> push

Improve the error message added in f8aae12 ("push: allow unqualified dest refspecs to DWIM", 2008-04-23, Git v1.5.5.2), 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 '[email protected]:avar/git.git'

This message needed to be read very carefully to spot how to fix the error, i.e. to push to refs/heads/newbranch.

Now the message will look like this instead:

$ ./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.
error: failed to push some refs to '[email protected]:avar/git.git'

This improvement is the result of on-list discussion in the thread "Re: [PATCH 2/2] push: add an advice on unqualified <dst> push" comment #1 (Oct. 2018) and comment #2, as well as my own fixes / reformatting / phrasing on top.

The suggestion by Jeff on-list was to make that second bullet point "Looking at the refname of the local source.".
The version being added here is more verbose, but also more accurate.
Saying "local source" could refer to any ref in the local refstore, including something in refs/remotes/*. A later change will teach guess_ref() to infer a ref type from remote-tracking refs, so let's not confuse the two.

And that is not all: there is a new setting now.

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 '[email protected]: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 config has a new advice:

pushUnqualifiedRefname:

Shown when git push 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.

Upvotes: 1

torek
torek

Reputation: 489093

TL;DR

You probably wanted:

$ git push remote 51447424149c671958a2f76ec1fefb135a5c2cea:refs/heads/WIP-51447424149c671958a2f76ec1fefb135a5c2cea

to create a branch named WIP-51447424149c671958a2f76ec1fefb135a5c2cea. (Be sure you really want to create that name, as it's kind of unweildy. It's valid and there is no problem with it, it's just a heck of a thing to type in.)

Long

What Git is complaining about takes a little bit of explanation:

  • A branch name is a special form of reference.
  • A reference is a string starting with refs/. The familiar two kinds of references are branch names and tags. (More about this in just a moment.)
  • References can be abbreviated ... sometimes, but not always.
  • Sometimes (wherever it makes sense to Git) you can use a raw hash ID instead of a reference.
  • git push takes a refspec, which is a pair of references separated by a colon (and optionally the whole thing can be prefixed with a plus sign).

What you're doing with git push is using the (very long) refspec 51447424149c671958a2f76ec1fefb135a5c2cea:WIP-51447424149c671958a2f76ec1fefb135a5c2cea. The left side of this refspec is the source reference, and the right side is the destination reference.

The thing on the left side of the colon is clearly1 a hash ID. So this is making use of the special case where you can supply a hash ID instead of an actual reference (as long as that object actually exists in your Git repository).

The thing on the right side of the colon, though, is a name, not a hash ID. This is good since this is one of the places that Git requires a name. But it's also a problem, because the name WIP-something does not start with refs/.

Note that Git explicitly complains about that:

The destination ... nor begins with refs/

Before we get to the rest, let's mention branches and tags again. A branch name like master is short-hand for the reference refs/heads/master. A tag name like v1.2 is short-hand for the reference refs/tags/v1.2. Note that in both cases, these start with refs/. They go on to name which kind of reference we're using:

  • A branch name reference starts with refs/heads/.
  • A tag name reference starts with refs/tags/.

In other words, when we say that branches and tags are forms of references, we're saying that given a reference, you can look at what comes right after refs/ and figure out what kind of reference it is: refs/heads/ means "branch" and refs/tags/ means "tag". (If you see refs/remotes/, that means it's a remote-tracking name; and there are yet more special words that go after refs/, such as notes/ for git notes.)

We also said above that references can sometimes be abbreviated. That's the first part of what Git is complaining about here, though:

... neither matches an existing ref on the remote ...

You're allowed to leave out the refs/heads/ part, and have the other Git—the one that your Git is pushing-to—figure out that master really means refs/heads/master. But this only works if they already have a refs/heads/master. If you're trying to create a new branch, you must tell the other Git: I'd like you to create a new branch.

You do this by giving the full name of the reference: refs/heads/WIP-something, for instance. The fact that it starts with refs/heads/ tells the other Git: I'd like to create a branch name. If you send them refs/tags/WIP-something, you are telling them to create a new tag name.

Anyway, this is why you're getting the rather long complaint, with its two parts: "neither ... nor". So the solution is to send them the full name.


1What, isn't it obvious? :-) This reminds me of the professors who prove theorems by doing six transformations and then saying "the rest is obvious...".

Upvotes: 24

Related Questions