正如标题所说,为什么会发生这种情况?
如文档和教程origin / master中所述 实际上是远程分支的本地副本。 那么为什么检查它会导致分离的HEAD,如果它是“只是分支的本地副本”
答案 0 :(得分:3)
这就是在Git中定义分支的方式。
具体来说,分支 - 即普通的普通本地分支 - 是一种参考。标签也是如此,远程跟踪分支也是如此。彼此之间的区别在于它的完整名称,就像你在一个名叫Bob的几个人的派对上一样,他们可能至少有不同的全名。
分支名称以refs/heads/
开头,而远程跟踪分支以refs/remotes/
开头,后跟远程名称。这意味着refs/heads/master
是分支名称,而refs/remotes/origin/master
是远程跟踪分支名称。
这些"参考"事物只是存储(一个,一个)Git对象的ID,通常是提交。
虽然我们将master
称为分支,但它实际上是分支名称。因此,它是一个引用,它存储单个提交的ID。哪个提交?好吧,它是分支的提示。但那么<形容词>是一个分支?
Git分支也是一组提交。 Git 找到集合的方式是从分支名称开始,它为分支提供了 tip 提交的ID。通过该提交,Git可以找到一个或多个早期提交,称为该提交的父。从这些提交中,Git可以找到他们的父母,依此类推,随着时间的推移。
当人们谈论"分支"在Git中,你必须从上下文中确定它们是否意味着"分支名称","分支上的提示提交",或者#34;该分支上的一些提交,可能同时排除该分支上的提交和其他一些分支。"
有关此问题的更多内容,请参阅What exactly do we mean by "branch"?
git checkout
分支名称时,您将被置于该分支使用git checkout master
或git checkout develop
,告诉Git您希望"进入"给定的分支。实际上这是如何工作的,Git将分支名称转换为完整的引用名称 - refs/heads/branch
- 并将该名称写入文件.git/HEAD
。也就是说,您的HEAD只是记录当前分支的名称。
在此(附加头)模式下,HEAD
文件充当间接引用。分支的尖端仍然记录在"真实"引用,以全名存储。由于好的或坏的原因(我们稍后会看到一些),Git 限制允许存储在HEAD
中的字符串:它们只能是以refs/heads/
。
由于refs/remotes/origin/master
不是以refs/heads/
开头,因此您根本不被允许在""" refs/remotes/origin/master
。同样,您不能使用refs/tags/v2.1
之类的标记:也不能以refs/heads/
开头。因此,如果您尝试查看其中一个,Git会让您进入"分离的HEAD"模式。
在"分离的HEAD"模式,Git记录.git/HEAD
文件中提交的原始哈希ID,而不是记录当前分支的名称。这意味着你不会" on"任何分支。但是,Git仍然允许您进行新的提交,或者在历史记录中移动:当您执行上述任何操作时,它会根据需要将新ID存储到.git/HEAD
。
大多数情况下,分离的HEAD模式适合查看历史记录。它也可以在git rebase
之类的命令下使用,它可以复制整个提交链,然后调整分支名称。
因此,如果HEAD
中有一个哈希ID,那么它就会被分离,这是您当前的提交。否则,HEAD
中有一个分支名称(以refs/heads/
开头),并且该分支名称存储("指向")分支的提示提交的ID
为了找出您所在的分支,Git会读取HEAD
。如果它有一个原始哈希ID,那么你就不会#34;"任何分支(虽然实际上你是在一个特殊的匿名分支上)。否则Git剥离refs/heads/
部分并将其打印为分支的名称。
在HEAD
中禁止远程跟踪分支机构名称的原因1:没有refs/heads/
剥离。
分支机构通过提交新提交而成长。要进行新的提交,Git:
HEAD
读取当前提交ID(如果它是间接的,则跟随它到分支引用)。HEAD
(如果它是间接的,则将其跟随分支引用)。这个新提交现在指向上一个分支提示,并且因为新ID现在存储在分支名称中,所以新提交现在是您的分支的尖端。继续!
但是这会立即导致原因2禁止远程跟踪分支:进行新的提交会导致您无法正确跟踪远程。远程跟踪引用应该指向提交您从遥控器获得,而不是你在当地制造的。
显然,这两个原因都可能有答案(例如,在远程跟踪分支或标签上禁止新提交,并在必要时拼出完整的引用)。但是Git设计师显然不喜欢这样,并且更喜欢"分离的HEAD"而是模式的东西。