Home > OS >  "head" equivalent in detached head state
"head" equivalent in detached head state

Time:06-17

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

git push origin head:something/something/blah

git will output the following error:

enter image description here

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.

CodePudding user response:

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.

CodePudding user response:

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.

  • Related