GIT:当有一个名为 HEAD 的分支时,如何明确引用当前的 HEAD



尽管"HEAD"对于 Git 分支的名称来说绝对是一个糟糕的选择,但它仍然是一个有效的分支名称。如果您碰巧有名为"HEAD"的分支,有没有办法明确地引用实际的HEAD符号引用?

分支可以引用为refs/heads/HEAD,但是HEAD本身呢?

仅使用 HEAD会导致<commit>作为参数传递的任何位置refname 'HEAD' is ambiguous错误。

根据 gitrevisions,如果HEADrefs/heads/HEAD都存在,则所选修订版HEAD(即,不是名为 HEAD 的分支)。

这实际上是大多数情况下的正确答案,但git checkout更喜欢分支名称而不是修订版,因此git checkout HEAD解析为分支,而不是当前提交。

还有其他命令也选择分支名称,例如,git branch -f HEAD newrevgit branch -D HEAD引用分支,但这里没有真正的歧义空间:git branch显然将在分支上工作。

其他处理程序通常将分支名称或修订说明符传递给git rev-parsegit rev-list,并且它们的行为与 gitrevisions 中记录的一样。

请注意,更现实的分支名称可能会发生类似情况。 就在昨天,我创建了一个用于处理某个以太网项目的分支,并将该分支命名为e1000...看起来像缩写的 SHA-1。 一个名为facade的分支也遭受了同样的命运。

好消息是,在 Git 2.16(2018 年第 1 季度)中,这个问题将不再容易出现,因为"git branch"和"git checkout -b"现在被禁止创建名称为"HEAD"的分支

参见 提交 662a4c8 (2017 年 11 月 14 日) by Kaartic Sivaraam ( sivaraam ).
请参阅提交 a625b09(2017 年 11 月 14 日),以及提交 bc1c9c0,提交 8280c4c (2017 年 10 月 13 日),作者是 Junio C Hamano ( gitster ).
(由Junio C Hamano -- gitster -- 2017年11月28日提交1616928合并)

branch:正确剔除refs/heads/{-dash,HEAD}

strbuf_check_branch_ref()是许多代码路径的中心位置查看建议的名称是否适合分支的名称.
它旨在让我们比一般用于 refnames 的check_refname_format()检查更严格,我们已经使用它来拒绝名称以 ' - '.
开头的分支该函数获取一个strbuf和一个字符串"name",如果名称不适合作为分支的名称,则返回非零值.
当名称正确时,它会在返回之前将具有建议名称的分支的完整 refname 放在strbuf中。

但是,事实证明,即使函数返回错误,一个调用者也会查看strbuf中的内容.
使函数填充strbuf,即使它返回错误.
这样,当"-dash"作为名称时,"refs/heads/-dash"被放置在strbuf中,当返回错误给copy_or_rename_branch()时,它会注意到用户正在尝试使用"git branch -m -- -dash dash"恢复将"-dash"重命名为"dash"。

同时,使用相同的机制也拒绝"HEAD"作为分支名称。

<小时 />

即使您试图"作弊",并使用git symbolic-refHEAD指向一个荒谬的引用(如" HEAD "!),这也不适用于 Git 2.38(2022 年第 3 季度):
" git symbolic-ref symref non..sen..se "(人)现在被诊断为错误。

请参阅提交 04ede97 (01 Aug 2022) 由 Linus Torvalds ( torvalds ).
(由 Junio C Hamano -- gitster -- 合并于 提交 8faaf69,2022 年 8 月 12 日)

symbolic-ref:拒绝设置语法无效的目标

签名者:Linus Torvalds
签名者:杰夫·金

您可以将绝对垃圾作为目标提供给符号引用,例如:

git symbolic-ref HEAD refs/heads/foo..bar

虽然这在技术上并没有完全破坏存储库(我们的"它是 Git 目录检测器在开始时只查找refs/"),但我们永远不会解析这样的 ref,因为".."在 refname 中无效。

让我们在创建时将这些标记为无效,以帮助调用者意识到他们要求的内容是虚假的。

一些注意事项:

  • 我们在这里使用REFNAME_ALLOW_ONELEVEL,它允许:

    git update-ref refs/heads/foo FETCH_HEAD
    

    继续工作.
    目前还不清楚是否有人想做点什么很奇怪,但它现在确实有效,所以这在保守方面是错误的。

  • 我们需要保持特定于 HEAD 的检查"它是否以 refs/".
    开头ALLOW_ONELEVEL标志意味着我们不会对其他参考强制执行,但 HEAD 在这里很特别,因为 validate_headref() 中的检查。

您将收到错误消息:

Refusing to set 'HEAD' to invalid ref 'xxx'

您可以在需要提交时使用 $(git rev-parse --quiet HEAD)(如果您想知道 HEAD"指向"的位置,则可以使用 $(git symbolic-ref HEAD))。

根据git help rev-parse $GIT_DIR/<refname>优先于refs/HEADrefs/tags/HEADrefs/heads/HEAD等,--quiet将消除"refname 'HEAD'是模棱两可的"警告。

在需要引用的任何地方,您都应该能够使用HEAD来引用当前签出的"事物",refs/heads/HEAD引用名为HEAD的分支。如果您在 Git 中找到一个需要 ref(而不是分支)HEAD不起作用的地方,那么您应该将其报告为错误。

最新更新