从存储库历史记录中删除大文件后,Git 存储库仍然很大

Posted

技术标签:

【中文标题】从存储库历史记录中删除大文件后,Git 存储库仍然很大【英文标题】:Git repo still huge after large files removed from repository history 【发布时间】:2011-10-16 14:14:56 【问题描述】:

我有一个(直到现在)使用 git 来存储其依赖项的代码库。存储库本身is available here(警告:它是巨大的)。不用说,我需要从存储库历史记录中删除依赖项,以便将其缩减到合理的大小。

我首先使用David Underhill's instructions 从历史记录中删除lib 目录。然而,即使在这样做之后,存储库仍然超过 300M。发出 git prunegit repack 会有所帮助,但仍然超过 180M。

为了找到任何臃肿的斑点,我发出了

git verify-pack -v .git/objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head

这些结果:

105526b5d3d398b9989d88c2f9fc2d1dc96a85b8 blob 35685609 33600527 31978828 d296935e6ac5f3f58b50c789394c9769116e9c34 斑点 35658016 33593241 112485744 50636f931180a32764edadd854968a971a083f8a blob 28360290 25897864 233390 b9e4dd37428e879a258f297b7f5bcfb9ba869695 blob 13108002 11640713 66661788 08d2720b2414aa07ce419b17d5f80c333c7313b7 斑点 12551621 11124009 89231035 6197a478a461275a0396f20c28487e9ae619a5f9 blob 11975135 11058259 148211988 1 50636f931180a32764edadd854968a971a083f8a 549eb0c73776fd0ede27a2fcb03366f76f45a13c blob 9136086 8166649 166451273 5bc0a0f04a7004bc16cfab1c091c6b369fb74049 斑点 9072616 8270262 80951514 741480238a6a6ce612cf089245dd46d6890fba9f blob 8858569 8080252 101294029 744226651c55b14c1aa8affb78fba4fdf02b577c blob 7412220 6766404 186825167

这就是我卡住的地方。我可以git show 这些 blob 并看到它们看起来非常像 jar 文件,但我不知道为什么它们仍在 repo 中。

find their filenames 的各种尝试都失败了。

git repack -agit repack -adgit repack -Ad似乎都没有效果。

【问题讨论】:

git ls-tree -r --long HEAD | cut -d" " -f4- | sort -r 可能会对您有所帮助。用历史中的每个提交替换 HEAD 并剪切最大的文件(也许过滤掉 lib/ 中的那些),它应该会给你一个线索。 【参考方案1】:

您是否尝试过运行git gc? http://www.kernel.org/pub/software/scm/git/docs/git-gc.html

【讨论】:

是的,git gc --aggressive --prune 事实上。这是 David Underhill 脚本的一部分,我也在其他各种错误尝试之间单独运行它。 如何将你想要的分支从一个仓库推送到另一个干净的仓库。 成功了,谢谢!我必须 git init 一个新的仓库,然后 git pull 我想要的分支。我不知道你可以拉入非克隆。 @Aaron:这可能意味着您的 blob 对于仍在 reflog 中的提交是必需的,即使它们不在任何分支上。 (默认情况下,Reflogs 持续 90 天。)Git 试图确保它不会删除任何重要的东西。有关如何覆盖的信息,请参阅 git-refloggit-gc 联机帮助页。是的,你总是可以拉入一个空的回购,因为“没有历史”总是与任何有效的历史一致。【参考方案2】:

您需要在存储库中的每个分支上运行David Underhill's 脚本,以确保从所有分支中删除引用。

然后,在进一步讨论中,使用git init 和原始存储库中的git pullgit remote add origin <original> 初始化一个新存储库,然后拉取所有分支。

$ du -sh ./BIG
299M ./BIG
$ cd BIG
$ git checkout master
$ git-remove-history REMOVE_ME
....
$ git checkout branch2
$ git-remove-history REMOVE_ME
...
$ cd ../SMALL
$ git init
$ git remote add origin ../BIG
$ git fetch --all
$ git checkout master
$ cd ..
$ du -sh ./SMALL ./BIG
26M ./SMALL
244M ./BIG

【讨论】:

【参考方案3】:

在 git gc 上使用 --prune=now

虽然您已成功将不需要的对象从历史记录中删除,但看起来这些不需要的对象并未被修剪,因为它们太年轻默认情况下无法修剪(请参阅configuration docs on git gc 了解更多细节)。使用git gc --prune=now 应该可以解决这个问题,或者您可以查看this answer 以获得更多核选项。

虽然这应该可以解决您的最后一个问题,但一个潜在的问题是难以找到大斑点以便使用git filter-branch 删除它们 - 我会说:

...不要使用 git filter-branch

git filter-branch 用于这样的任务很痛苦,并且有一个更好的、鲜为人知的工具 The BFG,专门设计用于删除 大文件 strong> 来自 Git 存储库。

删除大文件的核心命令如下所示:

$ bfg  --strip-blobs-bigger-than 10MB  my-repo.git

任何大小超过 10MB 的 blob(不在您的 最新 提交中)将从您的存储库的历史记录中完全删除 - 您无需手动查找自己的文件,受保护的提交中的文件是safe。

然后您可以使用git gc 清除死数据:

$ git gc --prune=now --aggressive

BFG 通常是 hundreds of times faster,而不是在大型 repo 上运行 git-filter-branch,并且选项是围绕这两个常见用例量身定制的:

删除 疯狂的大文件 删除密码、凭据和其他私人数据

全面披露:我是 BFG Repo-Cleaner 的作者。

【讨论】:

可能不相等,但至少相似且比--prune=now 更正式(参见手册页)是--prune=all (git 1.9.1)【参考方案4】:

我不小心在 git 中存储了我网站的大量 .jpa 备份 -

git filter-branch --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch MY_BIG_DIRECTORY_OR_FILE' --tag-name-filter cat -- --all

Relpace MY_BIG_DIRECTORY_OR_FILE 与相关文件夹完全重写您的历史记录,包括标签。

来源:

http://naleid.com/blog/2012/01/17/finding-and-purging-big-files-from-git-history

【讨论】:

以上是关于从存储库历史记录中删除大文件后,Git 存储库仍然很大的主要内容,如果未能解决你的问题,请参考以下文章

从 git 存储库中删除文件(历史记录)

sh 此脚本将帮助您从git repo历史记录中删除大文件,并缩小存储库的大小。

从存储库历史记录中删除提交 [重复]

如何在GIT Rebase Interactive Squash之后删除远程存储库上的历史记录提交消息

从 git/GitHub 的历史记录中删除文件夹及其内容

从旧的 Git 提交中删除私有信息