在一次旧提交中,添加了一个大文件。在多次提交之后,它被删除了,但是它停留在历史记录中,因此我试图通过以下命令从历史记录中删除该文件:
git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch src/main/resources/embed/linux/mongodb-linux-x86_64-3.2.0.tgz" --pru-tag-name-filter cat -- --all
该命令的结果如下:
Rewrite 9e96a248322ba6e85efde1e41498db0d41c1ee79 (3026/5151) (13917 seconds passed, remaining 9773 predicted) rm 'src/main/resources/embed/lib-linux-x86_64-3.2.0.tgz'
Rewrite 070cbe84ad8e1bc8f1ccec5294b600218d714e30 (4123/5151) (18963 seconds passed, remaining 4728 predicted) rm 'src/main/resources/embed/lib-linux-x86_64-3.2.0.tgz'
Rewrite 1f5604b332d6d48169fa398b60fc5ac42124d63d (5151/5151) (24005 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten
Ref 'refs/remotes/origin/master' was rewritten
....正如我从输出中了解到的那样,文件已从提交9e96a248322ba6e85efde1e41498db0d41c1ee79中删除,因此我检查如下:
git checkout 9e96a248322ba6e85efde1e41498db0d41c1ee79
ls src/main/resources/embed/linux/结果是mongodb-linux-x86_64-3.2.0.tgz。所以这个文件在历史上仍然存在。我做错了什么?我怎么才能随心所欲地移除它?
发布于 2019-01-08 17:33:00
据我从输出中了解,该文件已从commit 9e96a248322ba6e85efde1e1498db0d41c1ee79中删除。
git filter-branch删除了该文件,创建了一个新的提交。新提交具有不同的哈希,因为其内容不同。在运行git gc之前,使用散列9e96a248322ba6e85efde1e1498db0d41c1ee79的原始提交仍然存在。请注意,如果运行git log | grep 9e96a,将不会出现该哈希,因为相应的提交已不在历史记录中。
要更详细地理解这一点,我建议您阅读有关如何创建提交的文章。这篇博客文章解释得很好。Pro Git中的这一章详细介绍了git的内部管道以及如何创建提交。
发布于 2019-01-08 17:45:50
代码学徒的回答基本上是正确的,但要详细说明一下:
修改提交是不可能的。filter-branch (或任何历史重写机制)所做的是创建新的提交,这些提交“就像”现有的提交,但需要进行所需的更改。(例如,您的新提交文件中没有大文件,但否则它们看起来就像您以前的提交)
这有两个重要的后果。
首先,在重写分支的历史记录之后,任何拥有该分支副本的其他人都需要执行一些恢复步骤。您可以在git rebase文档中了解这些内容(在“从上游重基恢复”下)。如果他们做了错误的事情来恢复,它将撤消历史重写(将大文件放回历史中),因此您需要每个人在重写历史时进行合作。因此,重写历史有时是不切实际的。对于大型重写(特别是影响复杂历史、多个分支等的重写)通常情况下,最好是安排一次剪裁,每个人都放弃他们现有的克隆,然后从重写的回购重新克隆。
(其中的一个细微之处是,当您重写历史记录时,依赖于提交ID的任何工具或文档也会被破坏。)
第二,这意味着执行重写不会立即从回购中删除旧的提交。如果您试图从二进制膨胀中恢复空间,以及试图清除回购历史中的敏感信息泄漏,这一点都很重要。(在后一种情况下,几乎总是有必要将信息视为已泄露的信息。)
运行git gc可以是解决方案的一部分,但这还不够。这是因为在您完成重写之后,您的回购仍然有对旧提交的引用,因此gc不会将它们视为垃圾。至少,您需要清除重发;可能还有其他问题。
有一些方法可以做到这一点,但通常我通过从重写的回购中复制一个新的克隆来回避这个问题。那个克隆人不应该费心复制旧的/删除的历史。(要明确的是--我不认为有任何有记载的要求说这样的克隆不能复制已经失效的历史,但根据我的经验-至少在使用标准的git实现时-没有。)然后你可以摧毁原产回购和重建它从完全消毒的克隆。
https://stackoverflow.com/questions/54096687
复制相似问题