稍微扩展一下phd 的答案:在 Git 中,HEAD
像这样用大写字母拼写,1是一个非常特殊的名称。 HEAD
可以附加(到分支名称)或分离。在这两种情况下,Git 都能够告诉你你正在使用哪个提交:
git rev-parse HEAD
将打印一些哈希 ID。但只有当HEAD
附加到分支名称时,Git 才能告诉您您正在使用哪个分支名称:
git rev-parse --symbolic-full-name HEAD
git symbolic-ref HEAD
如果您在分支上,两者都会为您提供当前分支的名称(以 为前缀)。refs/heads/
如果您处于分离 HEAD 模式,则前者只会打印HEAD
,而后者将产生错误:
$ git checkout --detach master
HEAD is now at 7c20df84bd Git 2.23-rc1
Your branch is up to date with 'origin/master'.
$ git rev-parse --symbolic-full-name HEAD
HEAD
$ git symbolic-ref HEAD
fatal: ref HEAD is not a symbolic ref
许多形式的git checkout
将分离 HEAD
。一些表格会附上它。使用附加它,同时 - 如上所示 - 您可以添加以确保它变得或保持分离。git checkout branch-name
--detach
使用原始哈希 ID7c20df84bd
总是会导致分离的 HEAD,即使有一个或多个分支名称标识此特定提交。
请注意,您可以拥有任意数量的分支名称,它们都标识相同的提交:
$ for i in m1 m2 m3; do git branch $i master; done
$ git checkout m1
Switched to branch 'm1'
$ git rev-parse HEAD
7c20df84bd21ec0215358381844274fa10515017
$ git checkout m2
Switched to branch 'm2'
$ git rev-parse HEAD
7c20df84bd21ec0215358381844274fa10515017
如果我明确签出,您希望 Git 使用7c20df84bd21ec0215358381844274fa10515017
四个名称中的哪一个——<code>m1 m2
、、、m3
或——?master
但它没有使用它们:如果您希望它使用名称,则必须自己提供名称:
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
之后,我们可以删除额外的名称,以便提交7c20df84bd21ec0215358381844274fa10515017
只在, 的顶端master
,而不是同时在四个分支的顶端。
$ for i in m1 m2 m3; do git branch -d $i; done
Deleted branch m1 (was 7c20df84bd).
Deleted branch m2 (was 7c20df84bd).
Deleted branch m3 (was 7c20df84bd).
记住,HEAD
有两个功能。它找到当前分支(名称),如果HEAD
分离则找不到;并找到当前提交。2 你从 Git 得到的答案取决于你问的问题:你想知道分支名称,还是想知道当前的提交哈希 ID?
1在某些系统上,有时您可以将其拼写为小写字母head
, 并获得相同的效果。但是,这在添加的工作树中开始神秘地失败。最好坚持使用全大写HEAD
,或者如果输入太烦人,单个字符@
具有相同的特殊含义。
2这也可能失败,但仅限于特殊状态。您在一个新的、完全空的存储库中处于此状态,您当前的分支名称为master
,但分支master
本身尚不存在。这是因为分支名称必须包含某个现有的有效提交对象的哈希 ID。在一个新的、完全空的存储库中,根本没有提交。因此不允许存在分支名称。尽管如此,HEAD
还是附在名称上master
。
当你处于这种状态时——Git 的某些部分称其为孤立分支,如 in git checkout --orphan
,而其他部分称其为未出生的分支,如后git status
所述——你所做的下一次提交会导致分支名称出现。该名称已经在某个地方——具体来说,存储在其中——但是在首先创建了一个有效的提交之后,该名称将其HEAD
创建为一个有效的分支名称,该名称可以保存其哈希 ID。