微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

进行更改并以独立的状态提交它们 独立的HEAD模式 Reflogs 那你应该做什么?

如何解决进行更改并以独立的状态提交它们 独立的HEAD模式 Reflogs 那你应该做什么?

我使用git checkout <commit_SHA>访问了git树中的早期提交。 Git向我显示了以下消息:

You are in 'detached HEAD' state. You can look around,make experimental
changes and commit them,and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

这是否意味着当我返回到最近的提交(使用git checkout master)时,我在此处所做的任何更改(甚至通过提交更改)都不会保留?

解决方法

detached HEAD状态下的更改将一直保留,直到Git垃圾回收(GC)将其删除为止。

Detached HEAD上的文档非常好:

重要的是要意识到,在这一点上没有什么涉及提交最终提交 f(并通过扩展提交e)将被常规的Git垃圾回收过程删除,除非我们在此之前创建了引用。

这意味着,您可以checkout / switch到另一个引用的分支。 (例如git switch main),也可以创建一个新分支以使用git switch -c newbranchgit checkout -b newbranchname保留当前分离的工作树。

创建新分支时,工作树不在detached HEAD状态下,并具有引用。 (新的分支名称)

This answer介绍了如何禁用自动垃圾收集。

,

Git通过其哈希ID查找提交。哈希ID是那些笨拙的字母和数字字符串,例如e1cfff676549cdcd702cbac105468723ef2722f4。这些 look 是随机的,但不是。

如果您记下每个提交的哈希ID,则至少可以将它们找回来。但是,如果您在复制这些哈希ID时犯了错误或错字怎么办?最好让计算机保存它们。

这就是分支名称的作用。但是,实际上,它仅保存一个哈希ID。这就是您真正需要写下的所有内容。每次在“分离的HEAD”状态下进行新提交时,都必须记下刚刚进行的 new 提交的哈希ID。您可以擦除任何先前提交的哈希ID(尽管不必这样做)。

这就是全部的工作方式。每次提交保存内容:

  • 每个提交都存储每个文件的完整快照(Git在您或任何人进行提交时知道的快照)。这些文件以特殊的,压缩的,只读的,仅Git的格式存储,并且文件已被重复删除,因此,如果新的提交重用了旧提交中的大多数文件,则它们实际上不会占用任何空间。

  • 并且,每个提交都存储一些元数据:信息,例如您的姓名和电子邮件地址,以及一些日期和时间戳。在此元数据中,Git存储上一个提交的哈希ID,该ID在您刚进行的新提交之前。

因此,如果我们有一个连续的提交链,我们可以这样绘制它们:

... <-F <-G <-H

其中H代表这些提交的 last 的实际哈希ID。 Git可以使用哈希ID将提交H撤出其大型的所有提交数据库 1 。 Git保存了快照,再加上元数据。元数据存储先前提交G的原始哈希ID。

Git可以使用它来将提交G撤出其数据库,这将获得另一个保存的快照,以及G的元数据...包括早期提交{{ 1}}。因此,现在Git可以抓取具有快照和元数据的F。这种情况一直持续下去:Git从 last 提交到第一个提交,都是向后进行。

但是您或其他人还是必须获得Git这个 last 哈希ID。这就是分支名称有用的地方:根据定义,分支名称将 last 哈希ID存储在链中。如果您:

F

(或使用git checkout somebranch 做同样的事情),您会得到一些我们可能会绘制的东西:

git switch

特殊名称...--F--G--H <-- somebranch (HEAD) 会记住您告诉Git使用的哪个名称名称包含哈希ID HEAD。如果现在进行一次新提交,则Git将写出一个新提交,这将获得一个新的外观随机(但唯一且实际上不是随机的)哈希ID,我们将其称为H。然后,Git将I的哈希ID写入名称I

somebranch

这就是Git记住哪个提交是最后一个的方式。在分支名称中!


1 这个大数据库实际上包含Git的所有内部对象。提交只是四种类型的对象之一。 Git存储库基本上是两个数据库:一个大数据库和一个较小的数据库(通常较小),该数据库将名称(如分支名称)映射到哈希ID。较小的数据库可让您找到哈希ID,而较大的数据库可保存提交。


独立的HEAD模式

分离式HEAD 模式下,您告诉Git:不要在特殊名称...--F--G--H--I <-- somebranch (HEAD) 中存储名称,而是存储原始哈希ID代替。例如,假设您决定查看历史记录提交HEAD

G

现在,您可以查看提交...--F--G <-- HEAD \ H--I <-- somebranch 提交的文件。如果您现在进行一次 new 提交,则Git会像往常一样存储新提交:它会获得一些唯一的大型丑陋哈希ID,但我们将其称为G

J

现在假设您再次 J <-- HEAD / ...--F--G \ H--I <-- somebranch ,回到此:

git checkout somebranch

名称 J ??? / ...--F--G \ H--I <-- somebranch (HEAD) 现在拥有名称 HEAD,而不是提交somebranch的实际哈希ID。您将如何找到提交J

Reflogs

如果您将哈希ID记下来,那是找到它的一种方法。默认情况下,Git将挂起提交J至少30天,您可以查找哈希ID并再次输入。充其量是痛苦的。

Git还为您保存哈希ID (在Git称为 reflog 中)。使用reflog也有点痛苦。随时运行J,Git会向您显示git reflog reflog中的内容。哈希ID是HEAD所指向的每次提交的真实名称, 2 在过去30天内或更长的时间内是直接的(分离的HEAD)还是间接的(通过分支名称)。但是通常有数百种,而在maze of twisty little hash IDs,all alike中找到有用的 并不是一件好事。


2 这些是显示的缩写。它们还具有编号名称,例如HEADHEAD@{3}。每次Git添加reflog条目时数字递增,而哈希ID(缩写或完整)始终保持不变。


你应该做什么

如果您以后不希望再次查找提交,则只需在分离HEAD模式下继续工作即可。如果要做以后要查找它们,请创建一个新的分支名称。分支名称非常便宜:它们只是持有那些庞大的丑陋哈希ID之一。

使用HEAD@{14}可以在您现在所在的位置创建新的分支名称git branch newname。然后使用newnamegit checkout切换到它,以便将git switch附加到那个名称。或者,将这两个步骤结合起来:HEADgit checkout -b newname意味着创建名称,然后将其签出/切换为该名称

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。