我有一个300MB的git仓库。当前检出文件的总大小为2MB,剩余git仓库的总大小为298MB。这基本上是一个仅包含代码的仓库,不应该超过几MB。
我怀疑有人意外提交了一些大文件(视频、图片等),然后将它们删除……但没有从git中删除,因此历史记录仍包含无用的大文件。如何在git历史中找到这些大文件?由于有400多个提交,逐个查找不太实际。
注意:我的问题不涉及如何删除文件,而是如何首先找到它。
使用 --analyze
特性,就像下面这样使用git-filter-repo:
$ cd my-repo-folder
$ git-filter-repo --analyze
$ less .git/filter-repo/analysis/path-all-sizes.txt
--batch-check
不接受任何参数。下面的步骤在CentOS 6.5和Bash 4.1.2上尝试过。git cat-file --batch-check < <(git rev-list --all --objects | \
awk '{print $1}') | grep blob | sort -n -r -k 3
输出示例:
3a51a45e12d4aedcad53d3a0d4cf42079c62958e blob 305971200
7c357f2c2a7b33f939f9b7125b155adbd7890be2 blob 289163620
blobs.txt
的文件,其中仅包含 blob 哈希值,例如:3a51a45e12d4aedcad53d3a0d4cf42079c62958e
7c357f2c2a7b33f939f9b7125b155adbd7890be2
请做:
java -jar bfg.jar -bi blobs.txt <repo_dir>
这个问题是关于查找提交记录的,比查找Blobs工作量更大。想要了解,请继续阅读。
给定一个提交记录哈希值,一个打印与其相关联的所有对象哈希值(包括Blobs)的命令为:
git ls-tree -r --full-tree <commit_hash>
因此,如果我们能够对存储库中的所有提交进行这样的输出,那么给定一个 blob hash,一堆提交是与任何输出相匹配的。这个想法被编码在以下脚本中:
#!/bin/bash
DB_DIR='trees-db'
find_commit() {
cd ${DB_DIR}
for f in *; do
if grep -q $1 ${f}; then
echo ${f}
fi
done
cd - > /dev/null
}
create_db() {
local tfile='/tmp/commits.txt'
mkdir -p ${DB_DIR} && cd ${DB_DIR}
git rev-list --all > ${tfile}
while read commit_hash; do
if [[ ! -e ${commit_hash} ]]; then
git ls-tree -r --full-tree ${commit_hash} > ${commit_hash}
fi
done < ${tfile}
cd - > /dev/null
rm -f ${tfile}
}
create_db
while read id; do
find_commit ${id};
done
find-commits.sh
的文件中,则典型的调用方式如下:cat blobs.txt | find-commits.sh
如前所述,文件blobs.txt
列出了每行一个的blob哈希值。函数create_db()
在当前目录下的一个子目录中保存了所有提交列表的缓存。
以下是我在一台安装了两个Intel(R) Xeon(R) CPU E5-2620 2.00GHz处理器且被操作系统表示为24个虚拟核心的系统上进行实验得到的一些统计数据:
请注意,该脚本是单线程的。因此,在任何时候只能使用一个核心。
为了感受 git 历史中最后几次提交的“差异大小”
git log --stat
这将显示行数的差异大小:添加的行,删除的行