我有一个300mb的git回购。我目前签出的文件的总大小是2 MB,其余的git回购的总大小是298 MB。这基本上是一个只有代码的回购,不应该超过几MB。

我怀疑有人不小心提交了一些大文件(视频、图像等),然后删除了它们……但不是从git,所以历史仍然包含无用的大文件。如何在git历史中找到大文件?有400多个提交,所以一个接一个的提交是不实际的。

注意:我的问题不是关于如何删除文件,而是如何在第一时间找到它。


当前回答

我发现这个脚本在过去在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的提交。

其他回答

Powershell解决方案的windows git,找到最大的文件:

git ls-tree -r -t -l --full-name HEAD | Where-Object {
 $_ -match '(.+)\s+(.+)\s+(.+)\s+(\d+)\s+(.*)'
 } | ForEach-Object {
 New-Object -Type PSObject -Property @{
     'col1'        = $matches[1]
     'col2'      = $matches[2]
     'col3' = $matches[3]
     'Size'      = [int]$matches[4]
     'path'     = $matches[5]
 }
 } | sort -Property Size -Top 10 -Descending

我发现这个脚本在过去在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历史记录中追踪大文件?

从分析、确认和选择根本原因开始。使用git-repo-analysis来提供帮助。

你也可以在BFG Repo-Cleaner生成的详细报告中找到一些价值,它可以通过克隆到数字海洋液滴,使用10MiB/s的网络吞吐量快速运行。

步骤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年下半年的某个时候被删除了,但它的存档副本仍然可以使用时光倒流机访问。

我在苏黎世联邦理工学院物理系的维基页面上找到了一个简单的解决方案(接近该页的末尾)。只要做个git垃圾收集,把垃圾清除掉,然后

git rev-list --objects --all \
  | grep "$(git verify-pack -v .git/objects/pack/*.idx \
           | sort -k 3 -n \
           | tail -10 \
           | awk '{print$1}')"

将为您提供存储库中最大的10个文件。

现在还有一个更懒的解决方案,GitExtensions现在有一个插件,可以在UI中做到这一点(以及处理历史重写)。