正在从 Git 历史记录中删除大文件

Removing big files from Git history

我已经阅读了多个建议使用 filter-branch 或 BFG 来完成此任务的答案,但我觉得我需要进一步的建议,因为我的情况有点特殊。

我必须管理两个存储库,一个基本上是另一个的克隆,理想情况下,我希望每天将源中的更改拉入克隆。但是,原始存储库在其历史记录中包含非常大的文件,超出了 Github 的大小限制。所以我必须删除这些文件,但与此同时,除了对这些特定文件的更改之外,我不想损害现有的提交历史记录。据我了解,BFG 对历史进行了完全重写,这会让 Github 误以为所有现有文件都已删除并重新创建为新文件,而 filter-branch 不会这样做,但它也非常比较慢,我的存储库非常大,达到大约 100000 次提交...

所以我想找出解决这个问题的最佳方法。我应该在某些时候使用 BFG,并且简单地接受我会因为它的修改而看到荒谬的拉取请求,或者我应该以某种方式使用 filter-branch? 澄清一下,只有3个文件是造成这种不满的原因。

Git 中的提交历史不过是提交。

任何提交都不能更改。因此,对于 anything 从某个现有提交中删除一个大文件,那个东西——无论是 BFG、git filter-branchgit filter-repo 还是其他东西——都会必须提取 "bad" 提交,进行一些更改(例如,删除大文件),并进行新的改进的替代提交。

最糟糕的是每个后续提交都以不可更改的方式编码提交的原始哈希ID .错误提交的直接 children 将其编码为它们的 parent 哈希。因此,您或工具必须将 那些 提交复制到 new-and-improved 那些。他们的改进之处在于他们缺少大文件参考他们刚刚为最初的错误提交所做的替换。

当然,他们的 children 将 他们的 哈希 ID 编码为 parent 哈希 ID,因此现在该工具必须复制这些提交。这一直重复到每个分支中的 last 提交,由分支名称标识:

...--o--o--x--o--o--o   [old, bad version of branch]
         \
          ●--●--●--●   <-- branch

其中 x 是错误的提交:x 必须复制到第一个 new-and-improved 但随后所有后续提交也必须被复制。

作为不同提交的副本具有不同的哈希 ID。 每个克隆现在必须放弃"bad"提交——x一个及其所有后代——支持new-and-improved个。

所有这些 repository-editing 工具都应尽量减少更改。 BFG 可能是最快和最方便使用的,但是 git filter-branch 可以被告知只复制 所有 bad-and-descendant 提交并使用 --index-filter,这是它最快(仍然很慢!)的过滤器。为此,请使用:

git filter-branch --index-filter <command> -- <hash>..branch1 <hash>..branch2 ...

其中 <command> 是一个合适的 "git rm --cached --ignore-unmatch" 命令(请务必引用整个内容),并且 <hash> 和分支名称指定要复制的提交。请记住 A..B 语法意味着 不要查看提交 A 或更早的提交,而查看提交 B 和更早的 所以如果提交 x 是,比方说,deadbeefbadf00d...,你会想要使用其 parent 的散列作为限制器:

git filter-branch --index-filter "..." -- deadbeefbadf00d^..master

例如(用正确的删除命令填写 ... 部分)。

(注意:我没有实际使用过 BFG,但如果它 re-copies 不必要地提交,那真的很糟糕,我敢打赌它不会。)