【发布时间】:2011-09-15 13:17:15
【问题描述】:
我有一个 Git 存储库,其中包含几个巨大的媒体文件(图像和音频文件)。这些媒体文件的多个版本已陆续提交到 repo。这些文件是相同资产的连续精炼版本,它们具有相同的名称。
我只想在 Git 存储库中保留最新版本,因为它变得太大了。
最简单的方法是什么?
如何将这些更改正确传播到上游存储库?
【问题讨论】:
我有一个 Git 存储库,其中包含几个巨大的媒体文件(图像和音频文件)。这些媒体文件的多个版本已陆续提交到 repo。这些文件是相同资产的连续精炼版本,它们具有相同的名称。
我只想在 Git 存储库中保留最新版本,因为它变得太大了。
最简单的方法是什么?
如何将这些更改正确传播到上游存储库?
【问题讨论】:
查看 ProGit 书中Maintenance and Data Recovery 章节中关于“删除对象”的部分。它提供了有关如何从 git 存储库中删除对象的步骤。但请注意,它具有破坏性。
【讨论】:
如前所述,您将在这里重写历史记录,因此您必须让合作者(如果有)来做git rebase。
至于从历史记录中删除特定文件,Github has a nice walkthrough。
对于未来的解决方案,您应该考虑将二进制文件放在子模块中。
Git 的子模块支持允许存储库作为子目录包含外部项目的签出。子模块保持自己的身份;子模块支持仅存储子模块存储库位置和提交 ID,因此克隆包含项目(“超级项目”)的其他开发人员可以轻松地克隆同一修订版的所有子模块。超级项目的部分签出是可能的:您可以告诉 Git 不克隆任何子模块、部分或全部子模块。
【讨论】:
旧线程,但以防其他人在这里绊倒......
GitHub 和 Bitbucket 都推荐使用 BFG Repo-Cleaner。
见:
GitHub: Remove Sensitive Data
Bitbucket: Reduce Repository Size &
Bitbucket: Maintaining a Git Repository
删除超过 1 兆字节的文件以及不在 HEAD 中的 jpg、png 和 mp3 的示例:
# First get the latest bfg.jar, then:
$ git clone --mirror git://example.com/some-big-repo.git
$ java -jar bfg.jar --strip-blobs-bigger-than 1M --delete-files '*.{jpg,png,mp3}' some-big-repo.git
$ cd some-big-repo.git
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git push
注意:现在您已经推送了更新的版本,远程存储库也应该运行它git gc ...否则您不会看到大小减少。 (参见例如https://stackoverflow.com/a/28782154/3419541)
最后,重新克隆存储库,以确保您不会意外地重新提交旧的媒体文件 blob。
【讨论】:
git push --force origin <branch name, in my case master>(否则它会提示我重新集成我刚刚从本地存储库中删除的所有远程更改——我认为)。另外,我很傻,没有意识到如果我已经有一个最新的本地仓库克隆,那么 git clone 是不必要的:p
我有一个脚本 (github gist here) 可以从 git 存储库的整个历史记录中删除一些不需要的文件夹,或者删除除最新版本之外的所有文件夹。
假设所有 git 存储库都在 ~/repos 中是硬编码的,但这很容易改变。它还应该很容易适应处理单个文件。
【讨论】:
据我所知,这是无法做到的,因为在 git 中,每次提交都依赖于 整个 历史记录的 contents。因此,摆脱旧的大文件的唯一方法是“重播”整个提交历史(最好使用相同的提交时间戳和作者),省略大文件。请注意,这将产生一个完全独立的提交历史记录。
这显然不是一个非常可行的方法,所以教训可能是“不要使用 git 来版本巨大的二进制文件”。相反,您也许可以为文件创建一个单独的(忽略的)文件夹,并使用单独的系统对它们进行版本控制。
【讨论】:
origin,并让其他为您的项目做出贡献的人克隆一个新副本。
git filter-branch,但它确实看起来像我建议的自动化版本。同样,请注意,您最终将获得与旧历史不重叠的历史。但如果这是一个个人项目,那可能没问题。过滤后,您可以删除原始分支(在您 100% 确定过滤有效之后 - 我会在某处保留原始存储库的副本)并运行 git gc,这应该删除不存在的二进制文件历史的较长部分。