なぜあなたのGitリポジトリは「鉛のように」重いのか?
小さなプロジェクトを git clone するのに15分もかかったり、git fetch のたびにコーヒーを淹れに行く時間があるような状況に陥ったことはありませんか?私は以前、実際のソースコードはわずか120MBしかないのに、.git ディレクトリ が8GBまで膨れ上がったリポジトリを扱ったことがあります。
実のところ、原因が書いたコード自体にあることは稀です。犯人は、意図せず履歴(history)に放り込んでしまったものたちです。1GBの dump.sql ファイル、誤ってコミットされた node_modules フォルダ、あるいは二度と使われない何千もの古いタグなどです。Gitは非常に記憶力が良いため、対策を講じない限り、それらのミスを永遠に保持し続けます。
フォルダを一つずつ手動で調べる代わりに、私はよく git-sizer を使います。これは、リポジトリの負荷となっている要素を特定 し、診断してくれる「強力な武器」です。
Git-sizerとは何か、なぜ特別なのか?
通常、容量を確認するには du -sh .git コマンドを使いますが、この大まかな数字だけでは、なぜリポジトリが重いのかは分かりません。
git-sizerの利点は、Git内部の構造(objects、trees、blobs、commits)を分解して分析できる点にあります。以下の重要な指標を算出します:
- コミットの総数と単一コミットの最大サイズ。
- 容量を占有している上位のblob(ファイル)リスト。
- ディレクトリツリーの深さ(tree depth)。
- 存在するリファレンス(ブランチやタグなど)の数。
このツールは、リポジトリを0から30個以上の星(★)で評価します。星が多いほど、GitHubなどのサーバーから拒否されたり、同僚のPCでの動作が極端に遅くなったりするリスクが高まります。
git-sizerのインストール
Goで書かれた単一の実行ファイルなので、インストールは非常に迅速です。Homebrewを使っているmacOSユーザーなら、以下のコマンドを実行するだけです:
brew install git-sizer
WindowsまたはLinuxをお使いの場合は、GitHubのReleasesページからビルド済みバイナリをダウンロードしてPATHを通してください。また、すでにGoがインストールされている環境なら、以下のコマンドで直接インストールすることも可能です:
go install github.com/github/git-sizer@latest
実践: 「問題あり」なリポジトリを分析する
まずは、肥大化したリポジトリのディレクトリに移動し、以下のコマンドを実行します:
git-sizer --verbose
--verbose パラメータを付けると、具体的なファイルの詳細が表示されます。以下は、私が以前最適化したレガシープロジェクトの実際の結果です:
| Name | Value | Level of concern |
| ---------------------------- | --------- | ------------------------------ |
| Overall repository size | | |
| * Total size of blobs | 1.52 GiB | * |
| * Total size of trees | 85.2 MiB | |
| * Total size of commits | 12.4 MiB | |
| | | |
| Biggest objects | | |
| * Maximum blob size | 450 MiB | ******************** (20 stars)|
| * Maximum tree size | 1.2 MiB | ** |
| | | |
| History structure | | |
| * Maximum commit depth | 15,402 | **** |
Maximum blob size に20個の星が付いているのは、危険信号です。これは、履歴の中に少なくとも450MBの巨大なファイルが隠れていることを示しています。現在のコミットでそのファイルを削除したとしても、Gitは過去へのチェックアウトを可能にするために、.git 内にそれを保持し続けます。
犯人を突き止める
巨大なファイルがあることが分かったら、次のコマンドを使ってそのファイル名を特定します:
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print $1}')"
このコマンドは、git-sizerからのIDを実際のファイル名と照合します。あるプロジェクトでは、開発者が誤って600MBの video_demo.mp4 をコミットしていたのを見つけました。ファイル名が特定できれば、クリーンアップ作業は非常にスムーズに進みます。
分析後の最適化方法
単に rm file をして git commit するだけでは、この問題は解決しません。Gitの履歴全体を「手術」する必要があります。
1. git-filter-repo を使用する(推奨)
これは、古くなった git filter-branch よりもモダンで安全、かつ高速なツールです。履歴から巨大なファイルを完全に削除するには、以下を使用します:
git filter-repo --path path/to/large/file --invert-paths
重要な注意点: この操作は過去のコミットのハッシュ値を変更します。クリーンアップ後は、チーム全員が新しいリポジトリを再度クローンし直すように周知する必要があります。
2. 不要なリファレンスを掃除する
もしgit-sizerが Total number of references セクションで警告を出しているなら、リポジトリに不要なブランチやタグが多すぎます。メインブランチにマージ済みのブランチを削除するには、以下のコマンドを実行します:
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
リポジトリを常に「クリーン」に保つための秘訣
数GBのリポジトリを掃除するのは苦行です。同じ過ちを繰り返さないよう、私はチームに以下の3つの鉄則を課しています:
- 適切な .gitignore の設定: プロジェクト開始初日から、ログ、ビルド成果物、
node_modulesなどの依存関係フォルダを徹底的に除外します。 - Git LFS の活用: AIモデルや4K画像などの大きなファイルを扱う必要がある場合は、直接コミットせずに Git LFS を使用します。
- 定期的なチェック: 3ヶ月に一度はメインブランチで git-sizer を実行し、「迷い込んだ」ファイルがないか早期発見に努めます。
このプロセスを導入した後、チームのCI/CD速度は明らかに向上しました。ビルドサーバーへのコード取得(fetch)時間は5分から30秒未満に短縮されました。
Lời kết
git-sizer は直接問題を修正するものではありませんが、潜在的な問題をすべて見透かすための「顕微鏡」です。リポジトリが重すぎてクローンできなくなるまで待つ必要はありません。ぜひ今日、git-sizer を試してみてください。驚くような結果が出るかもしれませんよ!

