繁体   English   中英

在与主要提交相同的提交上分离 HEAD?

[英]Detached HEAD on same commit as main?

我不太确定在这种情况下我是如何获得我的存储库的,这甚至不再是一个问题,但我想了解发生了什么,所以下次我不会感到如此迷茫。

拉动时,我被警告说我处于分离的 HEAD 状态。 git status显示如下(截图):

HEAD detached at 44422b7

所以我跑了git log来找出我离 main 有多远,它显示了(截图):

commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD, main)

这对我来说没有多大意义,因为我似乎与主分支在同一个提交中,但是为了解决问题,我运行了git checkout main ,然后显示下一个git log截图),

commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD -> main)

一切都开始按照我最初的预期工作。

所以我试图理解git log在我第一次和第二次运行它时显示的区别(带有箭头的那个与只有一个逗号的那个),也许了解我是如何遇到这种情况的第一名。

感谢我能得到的任何帮助。

分支是指向提交的标签。

HEAD 总是指向当前签出的提交。

commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD, main)

commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD -> main)

两者都说你在提交 44422b74b6826291479ee7a17fe18bb4acca6355。 两者都说 HEAD 和该提交​​的要点。 但是HEAD -> main说 main 是当前签出的分支。

当您运行git commit时,会创建一个新的提交,并且当前签出的分支和 HEAD 会被移至它。

可能没有签出分支,这是一个分离的 HEAD 状态。 在这种情况下,当你git commit只有 HEAD 移动。 没有分支正在跟踪您的提交。 如果你git checkoutgit switch away,将(几乎)没有任何东西提到那些分离的提交。

有很多方法可以进入分离的 HEAD 状态,最基本的是检查提交 ID。 git checkout 4ba97c6ffc71f88a4de4ed88b188dbec2e5ff325

您可以通过检查分支来摆脱分离的 HEAD 状态,就像您所做的那样。 或者你可以在你所在的地方建立一个新的分支。

确保使用git switch main ,而不是git checkout main

通过使用git switch ,您可以降低以分离的 HEAD结尾的风险,因为您会收到错误消息(切换到提交或远程分支时)

fatal: a branch is expected, got remote branch 'origin/master'

您需要显式添加--detach选项才能得到一个分离的 HEAD。

这实际上是两个独立的问题:

  1. 试图了解 git log 在我第一次和第二次运行它时显示的内容之间的区别(带有箭头的那个与只有一个逗号的那个),

  2. 首先要了解我是如何陷入这种境地的。

问题 2 的答案是为什么我的 Git 存储库进入了分离的 HEAD 状态?

问题 1 的答案更简单:第一个显示 detached-HEAD 状态,第二个带有箭头的显示attached-HEAD 状态。 但是我们可以稍微解释一下:特别是“分离 HEAD”的整个概念首先有点奇特。 不过,在我们描述它之前,我们必须知道附加的 HEAD 是什么! 从某种意义上说,它是显而易见的——它与分离的 HEAD 相反——但这只是循环推理。 我们需要一些更基本的东西,这在于Git 如何找到提交

首先,请记住每个 Git 提交都有一个唯一的哈希 ID:

 commit 44422b74b6826291479ee7a17fe18bb4acca6355

那一大串难看的字母和数字是一个数字,用十六进制表示 (十进制是 389687007142770230305517186390235637298437448533,这实际上并没有更好。😀事实上,Git 必须使用十六进制或二进制,因为它在数据库中通过前缀查找这些信息的方式,部分使用了各种大小的 2 次幂。)此哈希 ID 用作简单键值数据库中的键; 该值是提交的内部 Git 表示。

所以 Git需要这个提交哈希 ID 才能找到这个提交。 您必须为 Git 提供哈希 ID:这是 Git 查找提交的唯一方法。 但是谁想一遍又一遍地输入44422b74b6826291479ee7a17fe18bb4acca6355呢? 你甚至会做对吗? 如果你可以只说main并且 Git 可以在辅助键值存储中查找main ——或者,技术上, refs/heads/main ——并找到44422b74b6826291479ee7a17fe18bb4acca6355怎么办? 那不是更好吗?

是的,它实际上更好,这就是我们所做的:我们输入mainv1.2origin/develop ,Git 在这个辅助数据库中查找它以获取原始哈希 ID。 从那里,Git 找到我们想要的提交。

当您“在分支上”时,正如git status所说,这意味着您所做的每个提交都会更新当前分支名称 因此,如果您on branch main并且您进行了的提交并且其哈希 ID 为a123456...或其他任何内容,Git 将存储提交的哈希 ID a123456...或其他名称,名称为main (旧的 commit-hash-ID 44422b74b6826291479ee7a17fe18bb4acca6355 - 进入新的提交,因此它现在是倒数第二个提交。)

反过来,意味着 Git 需要始终知道哪个分支名称是它应该在您进行新提交时更新的名称。 为了记住该分支名称,Git 将特殊名称HEAD “附加”分支名称。

(当前的实现是 Git 将ref: refs/heads/main写入.git/HEAD 。但是,这个实现在未来可能会发生变化。当前的实现已经与之前的不同,并且已经有所改变处理添加的工作树,因为现在它有时根本不是.git/HEAD :那只是用于工作树。)

所以这是一个附加的HEAD,因此......

附加的 HEAD是指 HEAD 包含分支的名称。 HEAD 中包含分支名称是当前分支。 分支名称本身,在充满名称到哈希 ID 映射的数据库中,包含当前提交的哈希 ID。 所以HEAD提供了两条信息:

  • 当前分支名称,和
  • 当前提交哈希 ID(间接)。

分离HEAD,Git 只需将某个提交(任何现有提交)的原始哈希 ID 写入HEAD 现在.git/HEAD包含一个原始哈希 ID,没有当前分支名称,但仍然有一个当前提交哈希 ID 只是HEAD现在直接持有了。 无需在名称数据库中查找名称。

你所做的一切仍然和以前一样工作:特别是,如果你创建一个的提交,新的提交会连接(向后,就像提交一样)到你创建新提交时当前提交; 现在新的提交就是当前的提交,即 Git 已将其哈希 ID 存储在HEAD中。

如果您确实进行了这样的提交并运行git log ,您将看到:

commit a123456... (HEAD)
[your new commit]

commit 44422b74b6826291479ee7a17fe18bb4acca6355 (main)
[your old commit]

由于git log当前提交开始并向后工作,因此一次提交一个。 但是由于您没有创建新的,因此名称HEAD名称main均表示“提交 44422b74b6826291479ee7a17fe18bb4acca6355”,因此您得到:

commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD, main)

附加HEAD后,Git 会使用该向前箭头符号打印它(因为 Git 2.10:在 2.10.0 之前,Git 打印HEAD, main两种情况)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM