git 仓库中,对不再存在的文件的体积进行统计

首先必须处在仓库中,然后用 https://stackoverflow.com/a/42544963/ 提供的方法提取出每个文件的大小,最后用 perl 计算总的体积。

git rev-list --objects --all |
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
  sed -n 's/^blob //p' |
  grep -vF --file=<(git ls-tree -r HEAD | awk '{print $3}') |
  sort --numeric-sort --key=2 |
  cut -c 1-12,41- |
  $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest > legacy.txt

perl -ne 'BEGIN{my $sum=0} s/.* (.*) .*/$1/g;
s/B//g;s/Ki/*1024/g;s/Mi/*1024*1024/g;s/Gi/*1024*1024*1024/g;$sum+=eval($_);
END{printf "%.1f MiB\n", $sum/1024/1024}' legacy.txt

把上面的 objectsize 换成 objectsize:disk 就能看到压缩后的文件总体积,在我们仓库中大概是 2216.4 MiB,而压缩前大概是 7304.1 MiB。

What this script displays is the size each file would have in the working directory. If you want to see how much space a file occupies if not checked out, you can use %(objectsize:disk) instead of %(objectsize). However, mind that this metric also has its caveats, as is mentioned in the documentation.

另外 git-filter-repo 也很好用,速度非常快。需要注意:

  1. 默认给出的分析文件不是按文件大小排序的,而是按照压缩后的文件大小排序的,所以按照文件大小筛选可能会意外删除一些文件。按照路径过滤是最靠谱的。
  2. 过滤的含义是保留,如果需要删除要加 --invert-paths 选项。