如何设置起始点/头部?

我建立了一个分支来追踪一个裁判。git checkout <branchname>会切换到那个分支,而 git status会告诉我分支离原点有多远,但令我惊讶的是 origin/HEAD仍然指向 origin/master而不是 origin/<branchname>

所以我的问题是,在什么情况下原点/头会被移动?

编辑:

我很欣赏关于 怎么做移动原点/HEAD 的答案,但我感兴趣的是什么“有机”移动它,外面我明确告诉它这样做。

例如,当我切换分支时,git 使 HEAD 指向我正在检查的分支,所以我很惊讶原点/HEAD 没有以相同的方式移动。

240412 次浏览

这是你作为本地回购所有者的设置,改变如下:

git remote set-head origin some_branch

起源/头部将指向您的分支,而不是主。这将只适用于你的回购,而不适用于其他人。默认情况下,它将指向 master,除非在远程回购中配置了其他内容。

手动输入远程机顶盒 提供了一些很好的信息。

编辑: 要强调的是: 如果没有你的命令,它“移动”的唯一方式就是像 重新命名主分支这样的案例,我不认为它被认为是“有机的”。所以,我会说,有机地,它不移动。

请记住,有 独立的 git 回购,我们正在讨论。您的本地回购与您的代码和远程运行在其他地方。

您是对的,当您更改分支时,HEAD 指向您当前的分支。所有这一切都发生在你们当地的 Git 回购上。而不是远程回购,它可能属于另一个开发人员,或者位于您办公室的服务器上,或者 github,或者文件系统上的另一个目录,等等。.

您的计算机(本地回购)没有业务更改远程 git 回购的 HEAD 指针。例如,它可能属于另一个开发人员。

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

那么什么会“有机地”更新起源/HEAD?应该是远程 Git 回收的活动。不是当地的回收站。

人们提到

Git sign-ref HEAD refs/HEAD/my _ other _ Branch

通常,当服务器上有一个共享的中央 git repo 供开发团队使用时,就会使用这种方法。它将是在远程计算机上执行的命令。您将看到这是远程 git 回购上的活动。

首先请注意,你的问题显示出一点误解。Origin/HEAD 表示远程控制器上的默认分支,也就是您调用的远程存储库中的 HEAD。当你在回购交易中切换分支时,你不会影响这一点。对于远程分支也是如此; 您的回购中可能有 masterorigin/master,其中 origin/master表示远程存储库中 master分支的本地副本。

只有当您或其他人在远程存储库 中实际更改它时,才会更改 Origin 的 HEAD,这基本上不会发生——您希望默认分支的公共回购在稳定分支(可能是 master)上保持不变。Source/HEAD 是一个本地参考,表示远程存储库中 HEAD 的本地副本。(它的全名是 refs/remote/source/HEAD。)

我认为上面回答了您实际想知道的问题,但是要继续回答您明确提出的问题... ... 当您克隆一个存储库时,source/HEAD 会自动设置,仅此而已。奇怪的是,它的 没有设置的命令,如 git remote update-我相信唯一的方式,它将改变是如果你手动改变它。(通过更改,我的意思是指向一个不同的分支; 显然,提交它指向如果该分支发生更改就会发生的更改,这可能发生在获取/拉取/远程更新时。)


编辑 : 下面讨论的问题在 Git 1.8.4.3中得到了纠正; 参见 更新


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

$ git remote show origin
* remote origin
Fetch URL: ...
Push  URL: ...
HEAD branch (remote HEAD is ambiguous, may be one of the following):
foo
master

奇怪的是,虽然这种方式打印的 HEAD 的概念会在远程上发生变化时发生变化(例如,如果去掉 foo) ,但它实际上并没有更新 refs/remotes/origin/HEAD。这会导致非常奇怪的情况。假设在上面的例子中,source/HEAD 实际上指向 foo,然后将 source 的 foo 分支删除。然后我们可以这样做:

$ 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 是主机,它也不会更新任何东西。陈旧的 foo 分支被正确地修剪,HEAD 变得悬空(指向一个不存在的分支) ,而且 还是不会更新它以指向 master。如果您想解决这个问题,那么使用 git remote set-head origin -a,它会像上面一样自动确定起源的 HEAD,然后实际设置 source/HEAD 来指向适当的远程分支。

免责声明 : 这是对 Cascabel 的回答的更新,我写这篇文章是为了节省好奇心。

我徒劳地试图复制(在 Git 2.0.1中) Cascabel 在他的回答中提到的 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 问题。

什么“有机地”移动起点/头部?

  • git clone将其设置一次到 HEAD 位于原点的位置
    • 它作为与 git clone克隆后要签出的默认分支

HEAD 在原点上代表什么?

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

什么设置起点/头部?

  • git clone获取并设置它
  • 如果 git fetch像其他引用一样更新它,那么它就有意义了,但是它没有
  • git remote set-head origin -a获取并设置它
    • 对于更新远程认为是“缺省分支”的本地知识非常有用

冷知识

  • 也可以将 origin/HEAD设置为任何其他值,而不需要联系遥控器: git remote set-head origin <branch>
    • 除了测试之外,我看不到任何用例
  • 不幸的是,没有任何东西能够在遥控器上设置 HEAD
  • 旧版本的 git 不知道 HEAD 在远程上指向哪个分支,只知道它最终拥有哪个提交散列: 所以它只是希望选择一个指向相同散列的分支名称
  • 参见@MichaWiedenmann 的评论: origin/HEAD用作通往分支的捷径,当你只命名一个远程

从 git CLI 运行以下命令:

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


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

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

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