git rebase:rebase提交仍在索引中?
当我读到这篇文章时,我明白了重定基础的提交应该会丢失。我之所以说应该,是因为我注意到,知道了重定基址的commit sha,我可以回忆起它。git rebase:rebase提交仍在索引中?,git,git-rebase,Git,Git Rebase,当我读到这篇文章时,我明白了重定基础的提交应该会丢失。我之所以说应该,是因为我注意到,知道了重定基址的commit sha,我可以回忆起它。 假设我有以下三个提交 A -> B -> C 其中C的sha是cshaid。然后,如果我使用git-rebase-I HEAD~2将修复C重新设置为B,然后使用git log检查结果,我会得到预期的结果,这意味着 A -> B' 其中B'的sha与B的sha不同。 但是,再次显示运行git log cshaid A -> B -
假设我有以下三个提交
A -> B -> C
其中C
的sha是cshaid
。然后,如果我使用git-rebase-I HEAD~2
将修复C
重新设置为B
,然后使用git log
检查结果,我会得到预期的结果,这意味着
A -> B'
其中B'
的sha与B
的sha不同。
但是,再次显示运行git log cshaid
A -> B -> C
问题:这是已知的行为吗?我试图阅读git rebase--help,但找不到相关信息。为什么不简单地忘记重定基础的提交?我的意思是,rebase是一种危险的操作,只有在您知道自己在做什么并且能够做到的情况下才能执行,这就是使用脏索引的意义所在(或者在保存这些无用提交的地方)?我错过什么了吗?
复制的步骤(以及更好地理解我的疑问)。如果您愿意再现这种情况,请尝试:
mkdir-sampledir&&cd-sampledir&&git-init
touch file&&git add-A.&git commit-m“Initial”
编辑文件,然后git提交-am“第一次修改”
编辑文件,然后提交git-am“第二次修改”
git日志
,您将看到三次提交,记住第二次修改的sha
git-rebase-i头~2
,将修复
第二次修改
转化为第一次修改
git log
,您将看到两个提交,其中第一次修改的sha现在与步骤5中的不同
是的,这是预期的行为。未引用的提交最终将被垃圾收集,从而从磁盘中清除。它们会保留数天(默认为14天),但在14天计时器开始计时之前,对象也必须从reflog中过期(默认情况下,无法访问的对象在30天后过期) 相关问题:
git-rebase
与其他以破坏性方式改变历史的命令一样,删除对过时提交的引用,但不会导致立即删除它,它在正常操作过程中定期自动执行,将(最终)从.git/objects
中删除实际提交数据(尽管将在一段时间内保持对提交的引用处于活动状态)
这是一个安全特性;使用git确实很难丢失数据。如果您确实想确保某些内容已丢失(例如,如果您意外提交了一个巨大的文件,并且希望收回磁盘空间),则需要使reflog条目过期并手动运行git gc
:
git reflog expire --expire=now --all
git gc --aggressive --prune=now
我知道重新设定的提交应该丢失
没有。不要迷路。在繁忙的repo中,git最终将垃圾收集那些从任何ref都无法访问并且已经存在一个月或更长时间的内容,但是除了git gc
,git操作只会添加到历史图中
移动标签对回购协议中的实际历史记录没有任何影响
。。。我知道重新设定的提交应该丢失
他们没有迷失,他们(故意)“被抛弃”(我的术语)
确实,rebase
复制了旧提交的内容。事实上,除了特殊的优化等,它基本上与执行git cherry pick
相同(并且交互式rebase脚本对每个“pick”操作使用git cherry pick
,对“squash”和“fixup”操作修改样式提交)
然而,存储库中的提交何时以及是否可见完全取决于其他因素。通常,git log
以您所在分支的名称开头,如HEAD
中所记录的(在.git
目录中有一个名为HEAD
的文件,其中包含字符串ref:refs/heads/master
,这就是git知道您“在分支主机上”的原因。1
给定一个分支名称,git通过“读取引用”将其转换为(单个)提交:
然后,log
命令可以通过其SHA-1读取提交对象。该提交对象有一些父SHA-1,并且git log
也读取这些SHA-1,依此类推,直到它到达一个没有父SHA-1的提交(“根”提交)
因此,给定根提交a
,第二次和第三次提交B
和C
——加上指向C
的标签master
:
A <-- B <-- C <-- HEAD=master
使B'
与git log
一起显示的是标签master
,是commitC的“剥离”和“粘贴到”commitB'
。更准确地说,分支主文件
(.git/refs/heads/master
)2的文件将使用B'
的新SHA-1重写:
A <-- B <-- C [no label, "abandoned"]
^
\
B' <-- HEAD=master
A删除了这些。我接受了你的回答,获得了额外的信息(如天数)和链接。默认的reflog过期时间是30天和90天(请参阅)。这属于30天类别。当然,无论哪种方式,您都不希望只假设reflog将永远保持不变。:-)@托瑞克:关于30天,你说得对,谢谢。更新了答案。reflog
为+1。我忘了在问题中提到,但当然,由于reflog
过期,仅仅在重定基址后进行垃圾收集是不够的
A <-- B <-- C
^
\
B'
A <-- B <-- C [no label, "abandoned"]
^
\
B' <-- HEAD=master