43

I have a working git repo. However, I miss the remotes/origin/HEAD -> origin/master when typing git branch -a. Why is the HEAD missing and how can I add the missing HEAD to my repo?

Dirk
  • 1,134
  • 2
  • 12
  • 21
  • 1
    Skip the accepted and go immediately to the [set-head answer](https://stackoverflow.com/a/73718128/659715) (don't forget to upvote!) – djeikyb Jun 22 '23 at 16:53

2 Answers2

58

Original Answer:

The origin's HEAD is only fetched when you clone the repo. If you otherwise add the remote (e.g. by using git remote add or by renaming another existing remote), this ref will not exist, because there is not reason to have it.

Remote repos should be bare repos in most cases, and in bare repos HEAD merely points to the "default" branch. This is only relevant at one time: when cloning. Therefore, after cloning, any remote HEADs are no longer important to your clone and Git will not fetch that ref from any remote.


As user lesmana requested, I looked into this again to find some more information:

"How to remove origin/HEAD?"

You do not have to do this.

The ref has no influence on the way your repo operates, and a ref is literally just a small text file on your file system, so it takes up nearly no space (just a few bytes).

If you still want to remove it, you can use

git update-ref -d refs/remotes/origin/HEAD

(if you want to remove a remote HEAD that is not on origin, use the respective remote's name instead).

"How to create origin/HEAD?"

As pointed out earlier, a remote HEAD ref is only used for cloning, and never required by Git at a later time. Unless you manually use it (which does not seem very useful, you can just use the branch it points to), there is no reason to manually create it.

Nevertheless, if you absolutely must, you can use

git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master

"Why is a remote HEAD not removed automatically by clone if it really is useless?"

There is no specific reason, from what I can tell, other than maybe inform the user explicitly of which branch is considered the default branch in the cloned remote repo. However, as I mentioned above, its existence causes no problems and uses up almost no space, so there is no real reason to remove it.

For more details, feel free to ask the Git devs directly at the Git mailing list :)

"What is the exact reason why clone needs it?"

None of the man pages explain directly that git clone always uses this, but it finds sidelong mentions in some places.

For example, man git clone says:

--branch <name>
-b <name>

Instead of pointing the newly created HEAD to the branch pointed to by the cloned repository’s HEAD, point to <name> branch instead. [...]

and

--[no-]single-branch

Clone only the history leading to the tip of a single branch, either specified by the --branch option or the primary branch remote’s HEAD points at. [...]

Furthermore, man gitrepository-layout says:

HEAD

[...] It does not mean much if the repository is not associated with any working tree (i.e. a bare repository), but a valid Git repository must have the HEAD file; some porcelains may use it to guess the designated "default" branch of the repository (usually master).

This means that

  • a) the remote repo itself must have the HEAD ref (to be valid), even though it is not semantically important (other than to point out the default branch)
  • b) git clone uses the remote repo's HEAD ref to determine where to point the local HEAD (unless you specify an override with --branch). To work with that ref, it must locally create it (therefore origin/HEAD). As mentioned above, it is then simply not deleted.
Community
  • 1
  • 1
Nevik Rehnel
  • 49,633
  • 6
  • 60
  • 50
  • can you please elaborate? how to remove it? is it really useless? how to create it, even if it is useless? bonus: why is it not removed automatically by clone if it really is useless? what is the exact reason why clone needs it? – Lesmana Oct 29 '14 at 22:45
  • 2
    `git update-ref -d refs/remotes/origin/HEAD` will remove both `refs/remotes/origin/HEAD` and `refs/remotes/origin/`. To remove only HEAD you can use `git remote set-head origin --delete`. – kolobok Nov 24 '17 at 15:30
  • With respect to "a remote HEAD ref is only used for cloning, and never required by Git at a later time" -- Perhaps it is not strictly required, but I think it is helpful in some cases. Some `git diff` commands in common usage fail if the remote HEAD is not defined. For an example see [fatal: ambiguous argument 'origin': unknown revision or path not in the working tree](https://stackoverflow.com/q/45096755). Granted, the diff commands in question are shorthand forms that will succeed when written in a more complete form, regardless of whether the remote HEAD is set. – cosmicdust Dec 13 '18 at 23:18
  • 3
    origin/HEAD is very useful from a user POV. For instance, I have this alias: `git w='log --graph origin/HEAD..'` which basically tells me what my PR would contain once my branch is pushed, independently from which branch is the main in the current repo (dev, master, main). – autra Jul 29 '22 at 08:58
7

The ref refs/remotes/origin/HEAD is useful not only for cloning. It is required if your Git repo contains submodules. Command git submodule update --remote expects that your submodules should have it:

$ git submodule update --remote
fatal: Unable to find refs/remotes/origin/HEAD revision in submodule path 'submodule-name'

So there is one more way to set or delete the default branch (the target of the ref refs/remotes/origin/HEAD).

Query the remote to determine the default branch and set it to the ref refs/remotes/origin/HEAD:

git remote set-head origin -a

For batch operation (execute for all submodules):

git submodule foreach git remote set-head origin -a

Set the ref refs/remotes/origin/HEAD explicitly to other existing branch (e.g. develop):

git remote set-head origin develop

Delete the ref refs/remotes/origin/HEAD:

git remote set-head origin -d

Look here for more details:

  1. https://www.sjoerdlangkemper.nl/2021/10/15/git-submodule-update-remote-retrieves-default-branch-except-when-changed/
  2. https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-headem
pratt
  • 1,534
  • 14
  • 17