我们有多个开发人员在共享git存储库上工作(他们推动这个)。
我们发现开发人员完成的某些提交会丢失。
我们可以使用gitk
命令(在Windows中使用)查看这些提交历史记录。
但是当我们去gitk中显示的提交中指定的文件并使用git log filepath
查看历史记录时,我们根本看不到提交。
我们不知道这是怎么发生的,也不知道如何恢复。
我们认为来自不同开发者的10多个提交都以这种方式丢失。
奇怪的是,我们使用git checkout 034534fd
查看了一些旧提交
并逐个完成git cherry-pick 234234321
提交。执行此操作时,我们收到了丢失的提交,但在“234234321”的提交日志中没有显示有关受影响文件的内容。
答案 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管理员仍可以根据需要删除所选提交。