【実務・中級編】Gitリポジトリを爆速化する:git-pack-refsとdelta compressionの仕組みを理解して最適化する – バージョン管理・CI/CD活用バイブル

巨大リポジトリを「爆速」に変える:Gitの深淵、パックファイルと参照最適化の極意

「`git status` に3秒かかる」「`git fetch` が終わらない」。そんな悲鳴が聞こえてきたら、君のチームのリポジトリは既に悲鳴を上げている。数千のブランチ、数万のコミットが重なれば、Gitは単なるバージョン管理ツールから「重たい足かせ」へと変貌する。

今日は、Gitの内部構造をハックし、物理的なパフォーマンスを限界まで引き出すための「禁断のチューニング」を伝授しよう。

—

1. なぜリポジトリは「重く」なるのか?

Gitの正体は単なるファイルシステムではない。「オブジェクトデータベース」だ。

  • ルーズオブジェクトの氾濫: 毎回コミットするたびに、`.git/objects` 配下に小さなファイルが大量生成される。ディスクI/Oが死ぬ原因だ。
  • 参照(Refs)の肥大化: `refs/heads/` に数千のファイルが散らばると、ファイルシステムのスキャンがボトルネックになる。
  • デルタ圧縮の劣化: 類似ファイルの差分を保持する「パックファイル(`.pack`)」の効率が悪化すると、計算コストが爆発的に増える。

これらを解決するのは、単なる `git gc` ではない。もっと深い部分を叩く必要がある。

—

2. 参照のパック化:`git pack-refs` の真実

数千のブランチを抱える現場では、`refs` ディレクトリ内のファイル数がパフォーマンスを直撃する。これを解決するのが `git pack-refs` だ。

参照を1つのファイル(packed-refs)にまとめ、ルーズな参照を削除する
git pack-refs –all –prune

なぜこれが効くのか?
通常、Gitはブランチ情報を個別のファイルとして読む。これを単一のテキストファイルに統合することで、ファイルシステムのオープン回数を激減させる。特にCI環境で数千のタグやブランチを扱う場合、これだけで `git fetch` の速度が体感レベルで変わる。

—

3. デルタ圧縮の限界突破:`git repack` の最適化

デフォルトの `git gc` は万人向けだ。プロは、リポジトリの特性に合わせて `repack` を微調整する。

デルタ圧縮のウィンドウサイズと深さを極限まで高める
git repack -a -d –depth=50 –window=250 –window-memory=1g

  • `–depth`: デルタチェーンの長さを指定。CPU性能が余っているなら大きくする。
  • `–window`: 圧縮時に比較するオブジェクトの数。メモリを食うが、パックファイルのサイズを劇的に縮小できる。

注意: これは低速なマシンで行うと終わらない。深夜のCIパイプラインや、強力なビルドサーバーで行うのがセオリーだ。

—

4. チーム開発を加速させる「神設定」の共有

個人の設定だけ速くても意味がない。`.gitconfig` をモジュール化して共有しよう。

`.gitconfig` のベストプラクティス

リポジトリ直下に `.gitconfig.shared` を置き、`git config –local include.path .gitconfig.shared` で読み込ませるのが鉄則だ。

.gitconfig.shared
[core]
# 巨大リポジトリではfsmonitorを有効化(変更監視をバックグラウンド化)
fsmonitor = true
# 圧縮レベルを最大に(CPUと引き換えにI/Oを削減)
compression = 9
# 並列処理の最適化
packedGitWindowSize = 1024m
packedGitLimit = 4096m

[gc]
# 自動GCを抑制し、メンテナンス時間を制御する
auto = 0
# プリパック後のルーズオブジェクト保持期間を短縮
pruneExpire = now

—

5. 伝説のエンジニアが選ぶ「導入すべきプラグイン」

1. [git-delta](https://github.com/dandavison/delta):
`git diff` の出力にシンタックスハイライトと行の差分表示を適用する。コードレビューの速度が「読む」から「スキャンする」に変わる。
2. [git-filter-repo](https://github.com/newren/git-filter-repo):
`git filter-branch` は忘れていい。巨大なバイナリを履歴から完全に消去し、リポジトリを「物理的に」軽量化するならこれ一択だ。

—

6. 実戦:爆速メンテナンスの自動化スクリプト

週に一度、cronやCIのメンテナンスジョブでこれを叩くことで、リポジトリの健康状態を維持する。

!/bin/bash
git-optimize.sh
リポジトリの健康を保つための最終手段

echo “Starting deep optimization…”
1. 参照のパック化
git pack-refs –all –prune

2. デルタ圧縮の再構成(ウィンドウサイズを最大化)
git repack -a -d -f –depth=50 –window=250

3. 未使用オブジェクトの完全削除
git prune –expire now

4. 書き込みインデックスの更新
git update-index –refresh

echo “Optimization complete. Repository is now lean.”

—

テックリードからの提言

Gitは「ツール」であると同時に「インフラ」だ。
「最近リポジトリが重いな」と愚痴をこぼす時間が、年間で何時間あるか計算してみろ。その時間は、本来コードを書き、設計を練り、未来を創るために使うべきものだ。

最適化は一度で終わらない。 リポジトリの成長に合わせて、パックファイルの構成戦略を常にアップデートせよ。それが、技術でチームの生産性を底上げするということだ。

さあ、今すぐ `git pack-refs` を実行して、その速さを体感してくれ。

タイトルとURLをコピーしました