如何在Git仓库中添加缺失的origin/HEAD

44
我有一个可用的Git仓库,但是当我输入`git branch -a`命令时,我发现缺少`remotes/origin/HEAD -> origin/master`。为什么会缺少HEAD,并且我该如何将缺少的HEAD添加到我的仓库中,同时保证不改变原来的意思?

1
跳过已接受的答案,直接转到设置为首选答案(别忘了点赞!) - djeikyb
2个回答

57

当你克隆repo时,只有源的HEAD会被获取。如果你通过其他方式添加远程库(例如使用git remote add命令或重命名现有的远程库),则该引用将不存在,因为没有理由存在。

在大多数情况下,远程仓库应该是裸仓库,在裸仓库中,HEAD只是指向“默认”分支。这只与克隆一次有关。因此,在克隆后,任何远程HEAD对你的克隆体已不再重要,Git将不会从任何远程获取该引用。

正如用户lesmana所请求的那样,我再次研究了一下,以找到更多信息:

"如何删除origin/HEAD?"

你不必这样做。

该引用对您的repo操作没有影响,而引用字面上仅是文件系统上的一个小文本文件,因此几乎不占用空间(只有几个字节)。如果你仍然想要删除它,可以使用:

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

(如果您想要删除不在origin上的远程HEAD,请使用相应远程的名称)。

"如何创建 origin / HEAD ?"

如前所述,远程HEAD引用仅用于克隆,并且Git在稍后的时间内从未需要。除非您手动使用它(这似乎并不是很有用,您可以直接使用它指向的分支),否则没有必要手动创建它。

尽管如此,如果您绝对必须,可以使用

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

"如果remote HEAD真的没用,为什么git clone不会自动删除它?"

据我所知,除了明确告诉用户克隆的远程仓库中哪个分支被认为是默认分支之外,并没有特别的原因。但正如上面提到的,它的存在并不会造成问题,也几乎不会占用任何空间,因此没有真正的理由将其删除。

如果需要更多细节,请随时在Git邮件列表中直接向Git开发人员询问 :)

"为什么git clone需要这个remote HEAD呢?"

从man页面中无法直接解释git clone总是使用它的原因,但可以在某些地方找到旁敲侧击的提及。

例如,man git clone说:

--branch <name>
-b <name>

不要将新创建的HEAD指向克隆存储库HEAD所指向的分支,而是指向<name>分支。[...]

--[no-]single-branch

仅克隆指向单个分支顶端的历史记录,可以是--branch选项或主要分支远程HEAD指向的分支。[...]

此外,man gitrepository-layout说:

HEAD

[...] 如果存储库未与任何工作树关联(即裸仓库),则它没有太大意义,但有效的Git存储库必须有HEAD文件;一些命令行程序可能会使用它来猜测存储库的指定“默认”分支(通常为master)。

这意味着:

  • a) 远程仓库本身必须具有HEAD引用(以便有效),即使它在语义上不重要(除了指出默认分支)
  • b) git clone 使用远程仓库的HEAD引用确定将本地HEAD指向何处(除非您使用--branch覆盖)。 为了使用该引用,它必须在本地创建(因此是origin/HEAD)。 如上所述,然后只是不被删除。

请您详细说明一下吗?如何删除它?它真的没用吗?即使它没用,如何创建它?另外,如果它真的没用,为什么克隆操作不会自动删除它呢?克隆操作需要它的确切原因是什么? - Lesmana
2
git update-ref -d refs/remotes/origin/HEAD 将删除 refs/remotes/origin/HEADrefs/remotes/origin/。如果只想删除 HEAD,则可以使用 git remote set-head origin --delete - kolobok
关于“远程HEAD引用仅用于克隆,以后Git永远不需要”--也许它并不是严格要求的,但我认为在某些情况下它是有帮助的。一些常见使用的git diff命令如果未定义远程HEAD,则会失败。例如,请参见致命错误:模糊参数'origin':未知的修订或路径不在工作树中。当然,所涉及的差异命令是缩写形式,无论是否设置远程HEAD,都将在更完整的形式中编写时成功。 - cosmicdust
3
origin/HEAD 对于用户来说非常有用。例如,我有这个别名:git w='log --graph origin/HEAD..',它基本上告诉我,无论当前仓库的主分支是 dev、master 还是 main,在我的分支推送后,我的 PR 将包含哪些内容。 - autra

8

refs/remotes/origin/HEAD 引用不仅在克隆时有用,如果您的 Git 存储库包含子模块,则它是必需的。 命令 git submodule update --remote 期望您的子模块应该具备它:

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

所以还有一种设置或删除默认分支(引用refs/remotes/origin/HEAD 的目标)的方法。

查询远程仓库以确定默认分支并将其设置为引用refs/remotes/origin/HEAD

git remote set-head origin -a

批量操作(对所有子模块执行):

git submodule foreach git remote set-head origin -a

将引用refs/remotes/origin/HEAD显式地设置为其他现有分支(例如develop):

git remote set-head origin develop

删除引用 refs/remotes/origin/HEAD

git remote set-head origin -d

更多细节请看这里:

  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

4
简而言之:git remote set-head origin --auto。这应该是被接受的答案。 - jpbochi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接