origin / HEAD如何设置?

时间:2012-01-12 18:03:16

标签: git

我设置了一个分支来跟踪ref in origin。 git checkout <branchname>会切换到该分支,而git status会显示我的分支距离原点前后多远,但我很惊讶origin/HEAD仍指向origin/master ,而不是origin/<branchname>

所以我的问题是,在什么情况下,起源/ HEAD会被移动?

编辑:

我很欣赏如何移动origin / HEAD的答案,但我对“有机”移动它感兴趣,除了我明确告诉它这样做。

例如,当我切换分支时,git使HEAD指向我正在检出的分支,所以我很惊讶origin / HEAD不会以相同的方式移动。

7 个答案:

答案 0 :(得分:149)

首先请注意,您的问题显示出一些误解。 origin / HEAD表示远程上的默认分支,即您正在呼叫原点的远程存储库中的HEAD。当您在回购中切换分支时,您不会影响它。远程分支也是如此;您的仓库中可能包含masterorigin/master,其中origin/master表示远程存储库中master分支的本地副本。

来源的HEAD只会在您或其他人在远程存储库中实际更改时发生变化,这基本上永远不会发生 - 您希望默认分支公共仓库在稳定分支上保持不变(可能是主人)。 origin / HEAD是一个本地引用,表示远程存储库中HEAD的本地副本。(其全名为refs / remotes / origin / HEAD。)

我认为以上内容回答了您真正想知道的内容,但是继续回答您明确要求的问题...在克隆存储库时会自动设置origin / HEAD,这就是它。奇怪的是,它是由<{1}}之类的命令设置的 - 我相信它改变的唯一方法就是手动更改它。 (通过更改,我的意思是指向另一个分支;显然,如果该分支发生更改,则指向更改的提交,这可能发生在fetch / pull / remote update上。)


修改:下面讨论的问题已在 Git 1.8.4.3 中得到纠正;见this update


但是,有一个小小的警告。 HEAD是一个符号引用,指向分支而不是直接指向提交,但git远程传输协议仅报告refs的提交。所以Git知道HEAD指向的提交的SHA1和所有其他引用;然后它必须通过找到指向同一提交的分支来推断HEAD的值。这意味着如果两个分支碰巧指向那里,那就不明确了。 (我相信如果可能的话它会选择主人,然后按字母顺序回到第一位。)你会在git remote update的输出中看到这个:

git remote show origin

奇怪的是,虽然如果遥控器上的内容发生变化,以这种方式打印的HEAD概念会发生变化(例如,如果foo被移除),它实际上并不会更新$ git remote show origin * remote origin Fetch URL: ... Push URL: ... HEAD branch (remote HEAD is ambiguous, may be one of the following): foo master 。这可能导致非常奇怪的情况。假设在上面的例子中,origin / HEAD实际上指向了foo,然后删除了origin的foo分支。然后我们可以这样做:

refs/remotes/origin/HEAD

因此即使远程节目知道HEAD是主节目,它也不会更新任何内容。正确修剪过时的foo分支,并且HEAD变为悬空(指向不存在的分支),并且不会将其更新为指向主分支。如果要解决此问题,请使用$ git remote show origin ... HEAD branch: master $ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/foo $ git remote update --prune origin Fetching origin x [deleted] (none) -> origin/foo (refs/remotes/origin/HEAD has become dangling) ,它会自动确定上面的原点HEAD,然后实际设置origin / HEAD指向相应的远程分支。

答案 1 :(得分:59)

这是您作为本地仓库所有者的设置。改变它:

git remote set-head origin some_branch

而origin / HEAD将指向您的分支而不是主分支。这将仅适用于您的回购,而不适用于其他回购。默认情况下,它将指向master,除非在远程仓库上配置了其他内容。

Manual entry for remote set-head提供了一些很好的信息。

编辑:强调:没有你告诉它,它“移动”的唯一方法就是像renaming the master branch这样的情况,我认为这不是“有机”的。所以,我会说有机地它不动。

答案 2 :(得分:20)

什么使“/ HEAD”有机地移动?

  • git clone将其设置为HEAD在原点的位置
    • 在使用git clone
    • 进行克隆后,它将作为结帐的默认分支

HEAD on origin代表什么?

  • 在裸存储库(通常是服务器上的存储库)上,它充当默认分支的标记,因为git clone以这种方式使用它
  • 在非裸存储库(本地或远程)上,它反映了存储库当前的结帐

什么设置起源/ HEAD?

  • git clone抓取并设置
  • 如果git fetch像其他任何引用一样更新它,那就没有意义,但它不会
  • git remote set-head origin -a抓取并设置它
    • 用于更新远程认为“默认分支”
    • 的本地知识

<强>琐事

  • origin/HEAD也可以在不联系遥控器的情况下设置为任何其他值:git remote set-head origin <branch>
    • 除了测试
    • 之外,我没有看到任何用例
  • 遗憾的是,没有任何东西能够在远程
  • 上设置HEAD
  • 旧版本的git不知道HEAD指向哪个分支,只知道它最终具有哪个提交哈希:所以它只是希望选择一个指向相同哈希的分支名称

答案 3 :(得分:10)

免责声明:这是Jefromi's answer的更新,我写这篇文章是为了挽救好奇的时间。

我徒劳地试图复制(在Git 2.0.1中)Jefromi在他的回答中提到的remote HEAD is ambiguous消息;所以我做了一些挖掘(通过克隆https://github.com/git/git并搜索日志)。它曾经是那个

Determining HEAD is ambiguous since it is done by comparing SHA1s.

In the case of multiple matches we return refs/heads/master if it
matches, else we return the first match we encounter. builtin-remote
needs all matches returned to it, so add a flag for it to request such.

(提交4229f1fa325870d6b24fe2a4c7d2ed5f14c6f771,日期为2009年2月27日,与git log --reverse --grep="HEAD is ambiguous"

一起发现

然而,此后的歧义已被解除

One long-standing flaw in the pack transfer protocol used by "git
clone" was that there was no way to tell the other end which branch
"HEAD" points at, and the receiving end needed to guess.  A new
capability has been defined in the pack protocol to convey this
information so that cloning from a repository with more than one
branches pointing at the same commit where the HEAD is at now
reliably sets the initial branch in the resulting repository.

(提交9196a2f8bd46d36a285bdfa03b4540ed3f01f671,日期为2013年11月8日,与git log --grep="ambiguous" --grep="HEAD" --all-match

一起发现

修改(感谢torek):

$ git name-rev --name-only 9196a2f8bd46d36a285bdfa03b4540ed3f01f671
tags/v1.8.4.3~3

这意味着,如果您使用 Git v1.8.4.3或更高版本,则不应遇到任何模糊的远程HEAD问题。

答案 4 :(得分:8)

请记住,我们正在讨论两个独立的git回购。您的本地仓库包含您的代码,而远程运行在其他地方。

你是对的,当你改变一个分支时,HEAD指向你当前的分支。所有这一切都发生在你当地的git repo上。不是远程仓库,可能由另一个开发人员拥有,或者位于办公室的服务器上,或github,或文件系统上的其他目录,等等......

您的计算机(本地存储库)没有业务更改远程git仓库上的HEAD指针。例如,它可能由不同的开发人员拥有。

还有一件事,您的计算机调用源/ XXX是您的计算机在最后一次获取时对远程状态的理解。

那么“有机”更新origin / HEAD会是什么?这将是远程git仓库的活动。不是你当地的回购。

人们提到了

  

git symbolic-ref HEAD refs / head / my_other_branch

通常,当服务器上有共享的中央git仓库供开发团队使用时,可以使用它。它将是在远程计算机上执行的命令。你会在远程git repo上看到这个活动。

答案 5 :(得分:1)

从git CLI运行以下命令:

# move to the wanted commit
git reset --hard <commit-hash> 

# update remote
git push --force origin <branch-name> 

答案 6 :(得分:0)

它由 git clonegit remote add -m master $url 设置。除此之外,您必须手动设置。

我也发送了一些补丁以使用 git fetch 进行更新(取决于某些配置)。在我看来,这将是更新它的最有机的方式。不幸的是,它们尚未合并。