我有一个300mb的git回购。我目前签出的文件的总大小是2 MB,其余的git回购的总大小是298 MB。这基本上是一个只有代码的回购,不应该超过几MB。
我怀疑有人不小心提交了一些大文件(视频、图像等),然后删除了它们……但不是从git,所以历史仍然包含无用的大文件。如何在git历史中找到大文件?有400多个提交,所以一个接一个的提交是不实际的。
注意:我的问题不是关于如何删除文件,而是如何在第一时间找到它。
我有一个300mb的git回购。我目前签出的文件的总大小是2 MB,其余的git回购的总大小是298 MB。这基本上是一个只有代码的回购,不应该超过几MB。
我怀疑有人不小心提交了一些大文件(视频、图像等),然后删除了它们……但不是从git,所以历史仍然包含无用的大文件。如何在git历史中找到大文件?有400多个提交,所以一个接一个的提交是不实际的。
注意:我的问题不是关于如何删除文件,而是如何在第一时间找到它。
当前回答
你应该使用BFG Repo-Cleaner。
根据该网站:
BFG是一个更简单、更快的git-filter-branch的替代方案 清除Git存储库历史中的坏数据: 删除疯狂的大文件 删除密码,凭证和其他私人数据
减少存储库大小的经典过程是:
git clone --mirror git://example.com/some-big-repo.git
java -jar bfg.jar --strip-biggest-blobs 500 some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push
其他回答
我发现这个脚本在过去在git存储库中查找大型(和不明显的)对象非常有用:
http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
#!/bin/bash
#set -x
# Shows you the largest objects in your repo's pack file.
# Written for osx.
#
# @see https://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
# @author Antony Stubbs
# set the internal field separator to line break, so that we can iterate easily over the verify-pack output
IFS=$'\n';
# list all objects including their size, sort by size, take top 10
objects=`git verify-pack -v .git/objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head`
echo "All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file."
output="size,pack,SHA,location"
allObjects=`git rev-list --all --objects`
for y in $objects
do
# extract the size in bytes
size=$((`echo $y | cut -f 5 -d ' '`/1024))
# extract the compressed size in bytes
compressedSize=$((`echo $y | cut -f 6 -d ' '`/1024))
# extract the SHA
sha=`echo $y | cut -f 1 -d ' '`
# find the objects location in the repository tree
other=`echo "${allObjects}" | grep $sha`
#lineBreak=`echo -e "\n"`
output="${output}\n${size},${compressedSize},${other}"
done
echo -e $output | column -t -s ', '
这将给你blob的对象名称(SHA1sum),然后你可以使用这样的脚本:
哪个提交有这个斑点?
…来查找指向这些blob的提交。
感受一下git历史中最后一次提交的“diff大小”
git log --stat
这将以行为单位显示差异大小:添加的行,删除的行
步骤1将所有sha1文件写入文本文件。
git rev-list --objects --all | sort -k 2 > allfileshas.txt
步骤2将blobs从大到小排序,并将结果写入文本文件:
git gc && git verify-pack -v .git/objects/pack/pack-*.idx | egrep "^\w+ blob\W+[0-9]+ [0-9]+ [0-9]+$" | sort -k 3 -n -r > bigobjects.txt
步骤3a结合两个文本文件,得到文件名/sha1/大小信息:
for SHA in `cut -f 1 -d\ < bigobjects.txt`; do
echo $(grep $SHA bigobjects.txt) $(grep $SHA allfileshas.txt) | awk '{print $1,$3,$7}' >> bigtosmall.txt
done;
如果您的文件名或路径名包含空格,请尝试步骤3a的这种变化。它使用cut而不是awk来获得从第7列到行尾的所需列包括空格:
for SHA in `cut -f 1 -d\ < bigobjects.txt`; do
echo $(grep $SHA bigobjects.txt) $(grep $SHA allfileshas.txt) | cut -d ' ' -f'1,3,7-' >> bigtosmall.txt
done;
现在可以查看bigtosmall.txt文件,以决定要从Git历史记录中删除哪些文件。
要执行删除(注意这部分很慢,因为它将检查历史记录中的每个提交,以获取关于您标识的文件的数据):
git filter-branch --tree-filter 'rm -f myLargeFile.log' HEAD
源
步骤1-3a是从Git历史记录中查找和清除大文件复制的
EDIT
这篇文章在2017年下半年的某个时候被删除了,但它的存档副本仍然可以使用时光倒流机访问。
如果你只想要一个大文件的列表,那么我想为你提供以下一行代码:
join -o "1.1 1.2 2.3" <(git rev-list --objects --all | sort) <(git verify-pack -v objects/pack/*.idx | sort -k3 -n | tail -5 | sort) | sort -k3 -n
其输出为:
commit file name size in bytes
72e1e6d20... db/players.sql 818314
ea20b964a... app/assets/images/background_final2.png 6739212
f8344b9b5... data_test/pg_xlog/000000010000000000000001 1625545
1ecc2395c... data_development/pg_xlog/000000010000000000000001 16777216
bc83d216d... app/assets/images/background_1forfinal.psd 95533848
列表中的最后一项指向git历史中最大的文件。
你可以使用这个输出来确保你没有删除你在历史中需要的BFG的东西。
注意,您需要使用——mirror来克隆您的存储库才能正常工作。
试试git ls-files | xargs du -hs——threshold=1M。
我们在CI管道中使用下面的命令,如果它在git repo中发现任何大文件,它就会停止:
test $(git ls-files | xargs du -hs --threshold=1M 2>/dev/null | tee /dev/stderr | wc -l) -gt 0 && { echo; echo "Aborting due to big files in the git repository."; exit 1; } || true