Git 有没有办法恢复在重新基址期间意外跳过的提交?
当一个有用的提交在重基操作期间被意外跳过时,Git是否有希望保留一个可以重新应用的对它的引用 这是一个包含大量二进制文件的非交互式rebase,我使用Git 有没有办法恢复在重新基址期间意外跳过的提交?,git,git-rebase,Git,Git Rebase,当一个有用的提交在重基操作期间被意外跳过时,Git是否有希望保留一个可以重新应用的对它的引用 这是一个包含大量二进制文件的非交互式rebase,我使用git-rebase--skip,长时间沉浸在一种愉快的触发情绪中,因此根本没有错误消息,只是一种糟糕的态度 这似乎是一个硬盘崩溃恢复场景,但与其追逐幻影索引节点,还不如找到一种方法来过滤.git/objects中丢失的树对象,并让它们重新激活。git reflog对您有用吗?我认为它应该仍然在垃圾收集器中,除非您运行git gc当您运行git r
git-rebase--skip
,长时间沉浸在一种愉快的触发情绪中,因此根本没有错误消息,只是一种糟糕的态度
这似乎是一个硬盘崩溃恢复场景,但与其追逐幻影索引节点,还不如找到一种方法来过滤
.git/objects
中丢失的树对象,并让它们重新激活。git reflog对您有用吗?我认为它应该仍然在垃圾收集器中,除非您运行git gc
当您运行git rebase
(交互式或非交互式)时,git基本上会执行一系列cherry pick
操作,以将原始提交链复制到新链。让我们对原始提交使用o
,并为分支branch
下的分支main
绘制提交图片段:
o1 - o2 - o3 - o4 <-- branch
/
..- * - x <-- main
上面的?
标签表示指向或指向提交o4
的git引用(分支名称、标记名称或任何其他合适的标签)。只要有一个指向它们的名字,你所有的旧提交仍然在那里。如果没有名字,它们仍然会一直存在,直到git-gc
清除它们(但您不希望发生这种情况,所以不要运行git-gc
:-)
那么,重要的问题是:“我们(和git)可以使用什么名称来查找o4
?”事实证明至少有两个:
- “reflog”中的一个或多个,以及
- 一个拼写为
ORIG_HEAD
ORIG_HEAD
是最容易使用的名称,但该名称也被其他命令使用(git merge
),因此您必须查看它是否仍然正确:
$ git log ORIG_HEAD
如果这给了你正确的链接,那么给自己一个更永久的名字,指向commito4
。这可以是一个分支名称(因此可以用一个新名称“复活”旧分支),也可以是一个标记名称,或者实际上是除分支和标记以外的任何其他名称:
$ git branch zombie ORIG_HEAD
(您不必这样做,随着对git的使用越来越熟悉,您可以跳过这一步,但在那之前这样做可能会更好。)
如果原始头被重击(例如,通过另一个重基、合并或其他方式),该怎么办?嗯,然后是回流
头有一个reflog,默认情况下,每个分支名称有另一个reflog。在这种情况下,要使用的是分支的reflog
:
$ git reflog branch
$ git log -g branch
$ git branch zombie branch@{yesterday}
$ git checkout branch # if needed
$ git reset --hard feedd0gf00d
但是您可以使用git reflog
来显示HEAD
的一个(这一个噪音更大,这就是为什么只查看分支
的一个可能更好的原因):
在所有输出的某处,您应该能够找到commito4
。您可能会发现许多类似于o4
的其他提交,这就是为什么git log-g
会很有帮助,因为它可以让您找到真正(或正确的)o4
在任何情况下,假设您最终提出了一个reflog风格的“相对名称”(如branch@{1}
或branch@{dayed}
),您可以找到原始SHA-1,或使用该相对名称,再次复活branch
的僵尸版本:
$ git reflog branch
$ git log -g branch
$ git branch zombie branch@{yesterday}
$ git checkout branch # if needed
$ git reset --hard feedd0gf00d
或:
或者别的什么
所有这些只会给你一个名字,zombie
,图中有三个问号。您仍然必须使用它来查找删除的提交,在本例中,commito2
。您可以通过原始SHA-1(通过读取git日志
)找到它,然后重新设置基址并将其拉入,或者选择它将副本附加到n4
,或者其他任何内容
如果您只想将分支
设置回提交o4
,您甚至可以完全取消僵尸分支,只需在分支上执行git reset--hard
:
$ git reflog branch
$ git log -g branch
$ git branch zombie branch@{yesterday}
$ git checkout branch # if needed
$ git reset --hard feedd0gf00d
或:
请注意,reset--hard
之后的事情就是任何commit-ID。--hard
使reset
清除您的工作树并将其替换为目标commit,而reset
操作本身告诉git:“使当前分支指向我将要提供给您的提交ID,而不考虑当前提交的分支提示名称。”
换句话说,在您的git重设基址
完成后,您发现在创建n1-n3-n4
链时遗漏了o2
,如果您立即git reset--hard ORIG_HEAD
,git会更改为:1
o1-o2-o3-o4没有“垃圾收集器”挂起的提交被存储到哪里,直到它们被垃圾回收。@perlsufi,可能是一个关于如何使用此命令跟踪和恢复跳过的提交的简短回执。我没有太多关于它在这个过程中如何有用的线索,手册页上的那些purge
词让我毛骨悚然。在reflog之后,获取你想要的SHA1,然后git合并该提交你说的在重新基址期间意外“跳过”的提交是什么意思?您是说在交互式重新基址期间,您将提交排除在编辑器列表之外,还是说重新基址没有像预期的那样应用提交?你使用的命令是什么?错误信息是什么?@Cupcake,这是一个非交互式的rebase,有很多二进制文件,我用git-rebase-skip
玩得太久了,所以根本没有错误信息,只是态度很糟糕。