0

Lets say I'm in a detached HEAD state and I run the following command:

git push origin HEAD:foo

git will output the following error:

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 'foo' on the remote side.
- Checking if the <src> being pushed ('HEAD')
  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: 'HEAD:refs/heads/foo'?
error: failed to push some refs to 'https://server/DefaultCollection/Project/_git/Repo'

So my question is: What is the correct keyword to use here instead of "HEAD" to reference the current commit I'm on? I can copy paste the commit id, but that's obviously silly. I'm asking for a constant name I can type, like head, to represent the current commit I'm on.

3
  • Why is copying the current commit id silly? If you really want a name toreference the current commit other than "HEAD" you can create a git tag to refer to the commit Commented Jun 16, 2022 at 15:58
  • 2
    Please don't post pictures of text. If your tools treat text as some sort of mysterious creature they can't deal with except as undifferentiated pixels, use better tools Screenshots are a horrible way of talking about code-related matters. xterm will do an html or svg screen dump that preserves colors and such in case that matters, surely every can do as well.
    – jthill
    Commented Jun 16, 2022 at 16:18
  • 1
    You should spell HEAD in all uppercase. Lowercase will sometimes work, and sometimes not. To see why, read my answer to HEAD vs head vs detached HEAD. (This isn't the issue here, it's just a general rule. The actual issue is the one in jthill's answer.) Note: if you don't like holding down the shift key that long, consider using @ instead of HEAD: it works the same and avoids typing three of the four characters.
    – torek
    Commented Jun 16, 2022 at 20:21

2 Answers 2

3

As jthill notes, when HEAD is detached, Git doesn't know whether:

git push origin HEAD:foo

is meant to create refs/heads/foo (a branch named foo) on origin, or refs/tags/foo (a tag named foo) on origin, or perhaps some other kind of ref (e.g., Gerrit's magic refs/for/foo1).

Because you are in detached-HEAD mode in your current working tree, you must assist Git here. You can:

git push origin @:refs/heads/foo

to tell Git: Use HEAD, in all upper case,2 to find the commit in my repository. Push that commit and any necessary parents to origin, then ask origin to create a branch named foo.

It's probably easier, though, to just go ahead and create a local branch named foo:

git switch -c foo

after which git push -u origin @ suffices. You might even wish to make an alias (shell alias or Git alias) or shell function out of this:

push-new-as foo

where push-new-as expands to git switch -c $1 && git push -u origin @ for instance. (Add additional protections, such as making sure there's no origin/foo first, if you like: that's probably actually a good idea. Have the alias-or-shell-function run git fetch origin first.)


1Gerrit is written in JGit and doesn't implement Git quite the same as C Git. Pushing to a refs/for/ namespace name creates a Gerrit changeset, which Gerrit sneakily renames into yet another name. Your own (probably C-Git based) Git thinks Gerrit created refs/for/foo successfully, as their JGit implemention returns a success indication at this point, but it really didn't. This little lie facilitates useful work and causes no actual problems, but it's definitely rather magic.

2See HEAD vs head vs detached HEAD for why the upper vs lower case distinction is important.

2
  • I actually like this answer better than mine.
    – jthill
    Commented Jun 16, 2022 at 21:02
  • 1
    git push origin HEAD:refs/heads/foo works well for me. I see now that it's actually directly in the error message, I just didn't understand it enough to see that. Thank you for the complete explanation! For some context, my use case for this is mainly sub-modules which pretty much always end up in a detached state regardless what you do. Don't really want the extra step of makin a local branch every time I need to push. I can use reflog to find the commit if I do something stupid and lose it rofl.
    – Simoyd
    Commented Jun 17, 2022 at 14:29
2

HEAD is your current checkout. If you don't say the destination type explicitly (by supplying the refs/<type>/ prefix, e.g. refs/heads/ for branch tips), Git tries to figure out what you meant by copying the type from the source. But when you don't have a branch checked out and you supply HEAD, there's no type to copy. It's just some random commit you're working on. That's what ... yeah, that error message you posted a picture of ... is talking about: you didn't say what kind of ref you're trying to create.

4
  • The question is about head, not HEAD.
    – matt
    Commented Jun 16, 2022 at 16:43
  • 2
    @matt but head isn't a branch or a tag in OP's repo, the error message says so, and OP mentioned "detached head state" as if they learned on a case-blind filesystem.
    – jthill
    Commented Jun 16, 2022 at 17:35
  • I'm afraid we don't know enough about what the user typed and what Git said in reply for us to know what the error message says or is responding to.
    – matt
    Commented Jun 16, 2022 at 18:10
  • 1
    @matt: it's true we can't be 100% positive. But I'm pretty sure.
    – torek
    Commented Jun 16, 2022 at 20:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.