Git: 找不到 blob - 想要从打包文件中删除它

13

我有一个很大的Blob文件,想要将它删除!我尝试使用以下方法删除该文件:http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/(我使用了-- --all而不是HEAD,以便从所有分支中删除文件)。

rm -rf .git/refs/original/ && git reflog expire --all &&  
    git gc --aggressive --prune

我通过这个为什么我的git存储库这么大查看了pack文件夹。

$ git verify-pack -v .git/objects/pack/pack-*.idx | sort -k3n
... last 4 lines:
bc7ae9801052180b283cd81880753549f0f92587 blob   19464809 749446 305054873
acd5f09a35846bec25ebc324738139e5caabc50f blob   294278199 71381636 39607483
986d152935434b56cf182d8a32e24cb57af75ac3 blob   480385718 108184804 110989119
ba9d1d27ee64154146b37dfaf42ededecea847e1 blob   761172819 27430741 277589990

这个脚本 git-find-blob 来自于 Which commit has this blob?

$ ./git-find-blob ba9d1d27ee64154146b37dfaf42ededecea847e1

但它什么都找不到。

有什么办法可以从我的存储库中删除它吗?


1
git status 的输出是否为空?这可能是因为 blob 已被添加到索引,但从未提交。 - Mark Longair
如果您同时包含 git for-each-ref --format="%(objectname)") 的输出以及不带 --cache 的相同命令,可能会很有用。 - Mark Longair
感谢您一如既往的关注,Mark; 在这个命令的两个变体中,Blob都被列为“unreachable blob”。在没有“--cache”标志的变体中,还列出了其他7个无法访问的blob。 - EoghanM
引用是否被打包?它是否出现在 git show-ref 中? - Josh Lee
@MarkLongair 谢谢!我尝试了所有方法来清理我的仓库中的2GB未引用blob,却没有意识到它们一直在索引中!(已标记为删除) - thenickdude
5个回答

8
您可以使用git repack -Ad强制Git重建您的包,并将无法访问的对象解压为松散的对象。在这一点上,您可以使用git gc --prune=now丢弃无法访问的对象。
您还应该仔细检查您是否实际过期了参考日志。我相信git reflog expire --all会默认为90天(或30天对于无法访问的对象),因此您可能需要改用git reflog expire --expire-unreachable=now --all(这需要在重新打包+垃圾回收之前执行)。

谢谢,那个方法有效!使用“reflog expire with unreachable=now”命令以及重打包后的“gc --prune=now”命令解决了问题。第一个命令清除了最后的引用,第二个命令则将对象本身删除。 - Harald Schilly
太好了!我也成功了。仓库从80 MiB降到了4.5 MiB。 - Leo

2
您想使用BFG Repo-Cleaner,它是一个更快、更简单的替代方案,专门用于从Git仓库中删除大文件。请下载Java jar(需要Java 6或以上版本),并运行以下命令:
$ java -jar bfg.jar  --strip-blobs-bigger-than 20M  my-repo.git

若有任何大小超过20M的Blob(且并未在您的最新提交中),将会从您的存储库历史记录中被完全移除。 您可以使用 git gc 来清除这些无用的数据:

$ git gc --prune=now --aggressive

BFG Repo-Cleaner通常比运行git-filter-branch快10-50倍,并且选项是围绕这两个常见用例进行调整的:

  • 删除超大文件
  • 删除密码、凭据和其他私人数据

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


2

首先,在你的git gc命令中,应该使用--prune=now,因为默认情况下会保留少于2周的对象。

其次,默认情况下你所使用的git-find-blob命令只在HEAD的历史记录中查找提交,所以如果该blob在另一个分支上,则该脚本将无法找到它。尝试按以下方式调用:

./git-find-blob ba9d1d27ee64154146b37dfaf42ededecea847e1 --all

我在 git-find-blob 的 Perl 和 Bash 版本上都尝试了 --all,但仍然没有结果。我还尝试在 gc --aggressive 上使用 --prune=now,但 blob 仍然存在! - EoghanM

1

在干净的推送的另一侧看不到 blob,所以这将是我的解决方案(推送到新位置,然后从该位置克隆)。有更简单的方法吗?


0

遇到了同样的问题。发现我的有问题的 blob 被一个无法访问的树引用。在 git-find-blob 脚本中添加:

git fsck --full --unreachable | \
while read unreachable obj tree
do
    if [[ ! $obj == "tree" ]]; then
        continue
    fi
    if git ls-tree -r $tree | grep -q "$obj_name" ; then
        echo "$unreachable $obj $tree"
    fi
done

我能够使用 BFG Repo-Cleaner 删除 blob,但如果我能使用本地 git 命令解决问题,我会更加高兴。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接