git 如何设置origin/HEAD?

uwopmtnx  于 2022-11-20  发布在  Git
关注(0)|答案(7)|浏览(305)

我设置了一个分支来跟踪origin中的引用。git checkout <branchname>切换到该分支,git status将显示我的分支距离origin有多远,但令我惊讶的是,origin/HEAD仍然指向origin/master,而不是origin/<branchname>
所以我的问题是,在什么情况下origin/HEAD会被移动?
编辑:
我很欣赏关于 * 如何 * 移动origin/HEAD的答案,但我感兴趣的是什么“有机地”移动它,在我明确告诉它这样做之外。
例如,当我切换分支时,git会让HEAD指向我要 checkout 的分支,所以我很惊讶origin/HEAD不会以同样的方式移动。

cygmwpex

cygmwpex1#

首先要注意你的问题有点误解。origin/HEAD代表远程上的默认分支,也就是你调用origin的远程仓库中的HEAD。当你在仓库中切换分支时,你不会影响它。远程分支也是如此;您的存储库中可能有masterorigin/master,其中origin/master表示远程存储库中master分支的本地副本。

origin的HEAD只有在您或其他人在远程仓库中更改时才会更改,这基本上不应该发生-您希望默认分支public repo在stable分支(可能是master)上保持不变。origin/HEAD是一个本地ref,表示远程仓库中HEAD的本地副本。(它的全名是refs/remotes/origin/HEAD。

我认为上面的答案是你真正想知道的,但是继续回答你明确提出的问题... origin/HEAD是在你克隆一个仓库时自动设置的,仅此而已。奇怪的是,它 * 不是 * 由git remote update这样的命令设置的--我相信唯一的改变它的方法是你手动改变它。(我所说的改变是指向一个不同的分支;很明显,如果分支发生变化,那么它所指向的提交也会发生变化,这可能发生在获取/拉取/远程更新时。)

编辑:下面讨论的问题已在Git 1.8.4.3中更正;请参阅this update

但有一点需要注意。HEAD是一个符号引用,指向分支而不是直接指向提交,但Git远程传输协议只报告引用的提交。所以Git知道HEAD和所有其他引用指向的提交的SHA1;然后,它必须通过找到指向同一提交的分支来推导HEAD的值。这意味着如果两个分支碰巧指向那里,它是不明确的。(我相信如果可能的话,它会选择master,然后按字母顺序福尔斯到第一个。)您将在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。这可能会导致非常奇怪的情况。假设在上面的例子中,origin/HEAD实际上指向foo,然后origin的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)

因此,即使remote show知道HEAD是master,它也不会更新任何内容。过时的foo分支被正确地修剪,HEAD变成了悬空的(指向一个不存在的分支),它 * 仍然 * 不会更新它以指向master。如果你想修复这个问题,使用git remote set-head origin -a,它会自动确定origin的HEAD,然后实际上设置origin/HEAD以指向相应的remote分支。

wnavrhmk

wnavrhmk2#

这是您作为本地存储库所有者的设置。请按以下方式更改它:

git remote set-head origin some_branch

origin/HEAD将指向您的分支而不是master。这将只适用于您的存储库而不适用于其他存储库。默认情况下,它将指向master,除非在远程存储库上配置了其他内容。
Manual entry for remote set-head提供了一些有关此方面的有用信息。
编辑:强调:如果没有你的命令,它“移动”的唯一方式是renaming the master branch,我认为这不是“有机的”,所以,我会说有机地,它不会移动。

46qrfjad

46qrfjad3#

什么会“有机地”移动原点/HEAD?

  • git clone将其设置为HEAD位于原点的点一次
  • 在使用git clone进行克隆后,它将作为默认的 checkout 分支
    原点上的HEAD表示什么?
  • 在空仓库(通常是“在服务器上”的仓库),它作为默认分支的标记,因为git clone以这样的方式使用它
  • 在非空存储库(本地或远程)上,它反映存储库的当前 checkout
    什么设置原点/HEAD?
  • git clone获取并设置它
  • 如果git fetch像更新其他引用一样更新它,则会有意义,但它没有
  • git remote set-head origin -a获取并设置它
  • 对于更新远程端所认为的“默认分支”的本地知识非常有用
    琐事
  • origin/HEAD也可以设置为任何其他值,而无需联系远程:git remote set-head origin <branch>
  • 除了测试之外,我没有看到其他使用案例
  • 不幸的是,没有任何东西能够在远程上设置HEAD
  • 旧版本的git并不知道HEAD指向远程节点上的哪个分支,只知道它最终拥有哪个提交哈希:所以它只是希望选择一个指向相同哈希的分支名称
  • 请参见@MichaWiedenmann评论:origin/HEAD仅在命名远程时用作分支的快捷方式
busg9geu

busg9geu4#

免责声明:这是对Cascabel's answer的更新,我写这篇文章是为了保存好奇的人一些时间。

我试图(在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或更高版本,你应该不会遇到任何ambiguous-remote-HEAD问题。

uidvcgyl

uidvcgyl5#

记住我们讨论的是两个独立的git repo。你的本地repo和你的代码以及在其他地方运行的远程repo。
你是对的,当你改变一个分支时,HEAD会指向你当前的分支。所有这些都发生在你的本地git repo上。而不是远程repo,它可能属于另一个开发者,或者位于你办公室的服务器上,或者github,或者文件系统上的另一个目录,等等。
您的计算机(本地存储库)没有权利更改远程git存储库上的HEAD指针。例如,它可能属于其他开发者。
还有一件事,你的计算机称之为origin/XXX的东西是你的计算机对上次获取时遥控器状态的理解。
那么,用什么来“有机地”更新origin/HEAD呢?应该是远程git存储库上的活动,而不是本地存储库。
人们提到
git symbolic-ref HEAD引用/head/我的其他分支
通常,当服务器上有一个共享的中央git存储库供开发团队使用时,会使用这个命令。它是在远程计算机上执行的命令。您会在远程git存储库上看到这个活动。

xzlaal3s

xzlaal3s6#

从git CLI运行以下命令:

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

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

ncgqoxb07#

它由git clonegit remote add -m master $url设置。除此之外,您必须手动设置它。
我也发送了一些补丁来更新git fetch(取决于一些配置)。在我看来,这将是最有机的更新方式。不幸的是,他们还没有被合并。

相关问题