33

我有一个 git repo,里面有一些非常大的二进制文件。我不再需要它们,而且我不关心能够从之前的提交中签出文件。因此,为了减少 repo 大小,我想从历史记录中完全删除二进制文件。

经过网络搜索,我得出结论,我最好的(唯一?)选择是使用git-filter-branch

git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_1.zip big_2.zip etc.zip' HEAD

到目前为止,这似乎是一个好方法吗?

假设答案是肯定的,我还有另一个问题要解决。git手册有这个警告

警告!重写的历史对于所有对象将具有不同的对象名称,并且不会与原始分支收敛。您将无法在原始分支之上轻松推送和分发重写的分支。如果您不知道全部含义,请不要使用此命令,并且无论如何都避免使用它,如果一个简单的单个提交就足以解决您的问题。(有关重写已发布历史的更多信息,请参阅 git-rebase(1) 中的“从上游 REBASE 恢复”部分。)

我们的服务器上有一个远程仓库。每个开发人员都会推入并从中拉出。根据上面的警告(以及我对git-filter-branch工作原理的理解),我认为我无法git-filter-branch在本地副本上运行然后推送更改。

所以,我暂时计划通过以下步骤:

  1. 告诉我所有的开发人员提交、推动和停止工作一段时间。
  2. 登录到服务器并在中央存储库上运行过滤器。
  3. 让每个人都删除他们的旧副本并再次从服务器克隆。

这听起来对吗?这是最好的解决方案吗?

4

4 回答 4

19

是的,您的解决方案将起作用。您还有另一个选择:不要在中央存储库上执行此操作,而是在您的克隆上运行过滤器,然后使用git push --force --all. 这将强制服务器接受来自您的存储库的新分支。这仅替换了第 2 步;其他步骤将相同。

如果您的开发人员非常精通 Git,那么他们可能不必删除旧副本;例如,他们可以获取新的遥控器并根据需要重新设置主题分支。

于 2010-12-14T20:55:49.460 回答
11

您的计划很好(尽管最好在存储库的裸克隆上执行过滤,而不是在中央服务器上),但git-filter-branch您应该优先使用我的BFG Repo-Cleaner,这是一种更快、更简单的替代git-filter-branch设计专门用于从 Git 存储库中删除大文件。

下载Java jar(需要 Java 6 或更高版本)并运行以下命令:

$ java -jar bfg.jar  --strip-blobs-bigger-than 1MB  my-repo.git

任何大小超过 1MB 的 blob(不在您的最新提交中)都将从您的存储库历史记录中完全删除。然后,您可以使用git gc清除死数据:

$ git gc --prune=now --aggressive

BFG 通常比运行快 10-50 倍,git-filter-branch并且这些选项是围绕以下两个常见用例量身定制的:

  • 删除疯狂的大文件
  • 删除密码、凭证和其他私人数据
于 2013-02-23T17:58:04.443 回答
5

如果您不让您的开发人员重新克隆,他们很可能会设法将大文件拖回来。例如,如果他们小心地拼接到您将创建的新历史记录上,然后碰巧git merge从一个本地项目分支不重新设置基准,合并提交的父级将包括项目分支,该分支最终指向您用git filter-branch.

于 2010-12-14T21:01:21.580 回答
3

您的解决方案不完整。您应该--tag-name-filter cat将过滤器分支作为参数包含在内,以便包含大文件的标签也会被更改。您还应该修改所有 refs 而不仅仅是 HEAD,因为提交可能在多个分支中。

这是一些更好的代码:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_1.zip big_2.zip etc.zip' --tag-name-filter cat -- --all

Github 有一个很好的指南: https ://help.github.com/articles/remove-sensitive-data

于 2013-07-16T21:43:59.300 回答