Git失去了历史上无法找到的承诺

时间:2012-03-07 14:14:57

标签: git

我们有多个开发人员在共享git存储库上工作(他们推动这个)。

我们发现开发人员完成的某些提交会丢失。

我们可以使用gitk命令(在Windows中使用)查看这些提交历史记录。

但是当我们去gitk中显示的提交中指定的文件并使用git log filepath查看历史记录时,我们根本看不到提交。

我们不知道这是怎么发生的,也不知道如何恢复。

我们认为来自不同开发者的10多个提交都以这种方式丢失。

奇怪的是,我们使用git checkout 034534fd查看了一些旧提交 并逐个完成git cherry-pick 234234321提交。执行此操作时,我们收到了丢失的提交,但在“234234321”的提交日志中没有显示有关受影响文件的内容。

4 个答案:

答案 0 :(得分:10)

我对你的问题感到有些困惑。您是说您可以在gitk但不能使用git log -- filepath看到提交内容吗?

如果是这样,你的提交不会丢失; git log的历史简化是将它们隐藏起来,因为它认为它们无趣。如果您将--full-history参数传递给git log,您应该会看到它们。

说明

默认情况下,当您执行git log -- filepath时,如果Git认为更改无趣,Git将不会向您显示该文件的更改。这被称为“历史简化”。这通常发生在樱桃选择中。

关于历史简化的文档(参见git help log)编写得不是很好(非常难以理解),但以下是关键部分:

  

默认模式

     

将历史简化为最简单的历史,解释树的最终状态。最简单的,因为如果最终结果相同(即合并具有相同内容的分支),它会修剪一些侧枝

     

[...]

     

如果对任何父母不是TREESAME,则包括提交(尽管可以更改,请参阅下面的--sparse)。如果提交是合并,并且它是一个父级的TREESAME,则只关注该父级。 (即使有几个TREESAME父母,也只能跟随他们中的一个。)否则,请跟随所有父母。

换句话说,当Git走过历史,寻找改变filepath并遇到合并提交的提交时,它并不总是遍历合并提交的所有父级。它通常只挑选一个父母,只走那个父母的祖先。这意味着如果提交位于其他分支之一中,您将看不到修改该文件的提交。

--full-history参数告诉git log遍历所有父项,从而显示修改filepath的每个提交是否Git认为它是否有趣。

答案 1 :(得分:2)

检查丢失的提交是否出现在git reflog的输出中。

答案 2 :(得分:2)

这可以通过提交分离的HEAD或删除提交所在的分支来实现。

如果您在reflog或rev-list中看到丢失的提交,那么最简单的方法是重新创建一个提示最后一次提交的分支:

git branch recovered <most-recent-SHA1>

提供要检索的最后一次提交的SHA1非常重要,否则以后的提交将不会显示。

现在提交位于名为recovered的分支中,因此您可以在日志中看到它们。您很可能希望合并或重新绑定recovered分支。

答案 3 :(得分:1)

只要您没有在本地存储库中运行垃圾收集并且存在git reflog,就可以创建基于最新SHA-1的新分支。 如果没有,那么像Gerrit这样的企业Git服务器的扩展将会执行将分支历史记录版本化的内容。如果以非快进方式删除或更新分支(push -f),它将在特殊引用下返回先前版本,以便在需要时可以恢复它们,并且不会被垃圾回收修剪。出于法律原因,Gerrit管理员仍可以根据需要删除所选提交。