300 MB の Git リポジトリがあります。現在チェックアウトしているファイルの合計サイズは 2 MB で、Git リポジトリの残りの部分の合計サイズは 298 MB です。これは基本的にコードのみのリポジトリであり、数 MB を超えることはありません。
誰かが誤って大きなファイル (ビデオ、画像など) をコミットし、その後削除したのではないかと思います...ただし、git からは削除していないため、履歴には役に立たない大きなファイルが残っています。git 履歴で大きなファイルを見つけるにはどうすればよいでしょうか? コミットは 400 件以上あるため、1 つずつ確認するのは現実的ではありません。
注:私の質問はファイルを削除する方法しかし、そもそもどうやって見つけるかが問題です。
ベストアンサー1
驚くほど高速なシェルワンライナー
このシェル スクリプトは、リポジトリ内のすべての BLOB オブジェクトを、小さいものから大きいものの順に並べ替えて表示します。
私のサンプル リポジトリでは、ここにある他のリポジトリよりも約100 倍高速に実行されました。私の信頼できる Athlon II X4 システムでは、 560 万のオブジェクトを含むLinux カーネル リポジトリを1 分強
で処理します。
ベーススクリプト
git rev-list --objects --all |
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
sed -n 's/^blob //p' |
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
上記のコードを実行すると、次のような人間が判読できる出力が得られます。
...
0d99bb931299 530KiB path/to/some-image.jpg
2ba44098e28f 12MiB path/to/hires-image.png
bd1741ddce0d 63MiB path/to/some-video-1080p.mp4
最初の列は、Gitオブジェクトデータベース内のファイル(BLOBオブジェクト)のIDです。ファイルを含むコミットを見つけるには、この BLOB はどのコミットにありますか?。
macOS ユーザー:numfmt
は macOS では利用できないため、最後の行を省略して生のバイト サイズを処理するか、 とすることができますbrew install coreutils
。
フィルタリング
さらにフィルタリングを行うには、行の前にsort
次のいずれかの行を挿入します。
に存在するファイルを除外するHEAD
には、次の行を挿入します。
grep -vF --file=<(git ls-tree -r HEAD | awk '{print $3}') |
指定されたサイズ(例: 1 MiB = 2 20 B) を超えるファイルのみを表示するには 、次の行を挿入します。
awk '$2 >= 2^20' |
コンピュータの出力
コンピューターによるさらなる処理に適した出力を生成するには、基本スクリプトの最後の 2 行を省略します。これらの行ですべての書式設定が行われます。これにより、次のような出力が残ります。
...
0d99bb93129939b72069df14af0d0dbda7eb6dba 542455 path/to/some-image.jpg
2ba44098e28f8f66bac5e21210c2774085d2319b 12446815 path/to/hires-image.png
bd1741ddce0d07b72ccf69ed281e09bf8a2d0b2f 65183843 path/to/some-video-1080p.mp4
付録
ファイルの削除
実際のファイル削除については、このトピックに関するSOの質問。
表示されるファイルサイズの意味を理解する
このスクリプトは、各ファイルが作業ディレクトリで占めるサイズを表示します。チェックアウトされていない場合にファイルが占めるスペースを確認したい場合は、%(objectsize:disk)
の代わりにを使用できます%(objectsize)
。ただし、このメトリックにも注意点があることに留意してください。ドキュメンテーション。
より洗練されたサイズ統計
大きなファイルのリストだけでは、問題の原因を特定できない場合があります。たとえば、膨大な数の小さなファイルを含むディレクトリやブランチを見つけることはできません。
したがって、ここでのスクリプトがあなたに合わない場合(そしてgitのかなり新しいバージョンを持っている場合)、git-filter-repo --analyze
またはgit rev-list --disk-usage
(例)。