"(no branch)"和"(detached at abc1234)"之间的区别是什么?

4
通常情况下,当你在git仓库中运行以下命令时: ```bash ```
git checkout abc1234

您会进入一个分离的 HEAD 状态。如果运行 git branch 命令,输出将会类似于下面这个样子:

* (detached from abc1234)
  master

这是正常且预期的行为。

最近我一直在尝试使用pygit2,发现了一些以前没有见过的东西。假设我执行以下操作:

repo = pygit2.discover_repository("/path/to/repo")
repo.head = "abc1234"

我希望仓库处于分离头状态。在此之后,我相信实际上是这样的。但是,git branch 的输出结果看起来有些不同:

* (no branch)
  master

有人知道差异是什么,为什么会有差异以及它代表了什么吗?

编辑:

下面是使用pygit2克隆存储库、将提交SHA1哈希分配给repo.head、然后运行git checkout mastergit checkout myhash后的reflog:

69df316 HEAD@{0}: checkout: moving from master to 69df3161f315e9b13ba4bd811635c11f67616598
d6ece61 HEAD@{1}: checkout: moving from 69df3161f315e9b13ba4bd811635c11f67616598 to master
69df316 HEAD@{2}:
d6ece61 HEAD@{3}: clone: from file:///path/to/repo

这可能只是一个标签吧?我的意思是,当程序进行操作时,它看起来像是可以设置的标签。 - Jean Hominal
3个回答

5
当git处于“detached HEAD”状态时,会根据reflog的内容显示“(no branch)”或“(detached from abc)”。在您的代码中,您只是简单地覆盖该值而没有提供任何消息,因此没有将任何消息写入reflog(如您的reflog中的HEAD@{2}条目所示)。如果有类似的“checkout”消息,则会出现分离的文本。 pygit2提供了Reference.log_append()来向日志追加条目,因此您可以创建此类条目,尽管目前它仍会创建空条目)。解决方案是一旦支持libgit2 0.21引入的较新的reflog处理方式,就使用更新方法。 设置引用的方法Reference.set_target()和Repository.set_head()提供了一个位置来放置您自己的身份和消息以供reflog使用,您可以使用它们提供与git checkout命令创建的消息等效的消息。
您可以尝试像当前一样进行更新,并手动编写reflog中的条目(它在.git / logs / HEAD下,是一个文本文件),以模仿git将写入的消息,并且您应该看到“(detached from abc)”消息出现。

2

在第一个例子中,Git 意味着您已检出了一个提交(而不是分支),因此您的 HEAD 已分离。

在第二个例子中,Git 表示您已经检出了无效的内容。您没有处于分离的 HEAD 状态,您的 HEAD 指向一个无效的分支,具体来说,它指向了一个与您提交 ID 的名称相同的分支。

您向 repo.head 指定了一个字符串参数,好像它是一个分支名称。(pygit2 忠实地将 HEAD 设置为该分支名称,但实际上该分支不存在。)相反,您需要指定一个 Oid,以表明 HEAD 应该分离:

repo.head = Oid(hex="abc1234...")

1

检查两种情况下git的版本是否相同。
Junio C Hamano的文章“编程方式检查当前分支”中指出:

实际上,自从1.8.3发布以来,当你不在任何分支上时,输出结果已经变成了这样:

$ git checkout v1.8.3
$ git branch
* (detached from v1.8.3)
  master
  next

这意味着第二个输出 "(no branch)" 与使用 git pre-1.8.3 一致,或者与 pygit2 使用较旧版本的 libgit2 相符,正如 Jean Hominal 所评论的那样。请保留html标签。
如果这是由同一个git生成的,则检查HEAD的内容:参见“用户手册”。

HEAD将引用提交的SHA-1而不是分支,并且git branch将显示您不再处于分支上:

$ cat .git/HEAD
427abfa28afedffadfca9dd8b067eb6d36bac53f
$ git branch
* (detached from v2.6.17)
master

然而,在第二种情况下,如果pygit2根本没有设置HEADwt_status.c将显示no branch

除了 pygit2 不直接使用标准的 git 实现,而是使用重新实现的 libgit2 - Jean Hominal
@JeanHominal 确实,我已经将您的评论包含在答案中以增加可见性。 - VonC
(无分支)”的输出来自于与输出“(分离在abc1234处)”相同版本的git,即git v2.1.0。我正在使用最新版本的pygit2和libgit2(通过官方的Arch Linux存储库),但不知道libgit2实现的是哪个版本的git。 - Matthew G
1
在这两种情况下,“.git/HEAD”的内容都是已检出的提交的SHA1哈希值。 - Matthew G
@MatthewG 在一个案例中有 .git/ORIG_HEAD,而在另一个案例中没有。 - VonC
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接