Gitリポジトリの「死肉」を喰らう:git-pruneとreflogによる極限の最適化術
チーム開発において、Gitリポジトリが数GBに肥大化し、「`git fetch`にやたら時間がかかる」「クローンするたびにコーヒーを淹れに行く」という状況に陥っていないか?
それは、君たちが過去に捨てたブランチ、書き換えたコミット、そして巨大なバイナリが、リポジトリの深淵で「ゾンビ」として生き続けているからだ。Gitは親切心からデータを簡単には消さない。だが、その親切心がチームの生産性を殺している。
今日は、Gitの深層構造を理解し、不要なオブジェクトを完全に葬り去る「断捨離」の極意を伝授する。
—
1. なぜリポジトリは肥大化するのか?(ゾンビオブジェクトの正体)
Gitは「追記型」のデータベースだ。`git commit`や`git checkout`をするたび、オブジェクトが生成される。問題は、`git branch -d`でブランチを消しても、コミットオブジェクトそのものは消えないことにある。
これらは「到達不能(unreachable)なオブジェクト」となり、`.git/objects`の中で埃をかぶる。さらに、間違えてコミットしたパスワードや巨大バイナリは、過去の履歴を辿ればいつでも復元できてしまう。これを放置すると、リポジトリは物理的に肥大化し続け、転送量を圧迫する。
—
2. 駆除の前に:reflogという「命綱」
「怖くて消せない」というエンジニアのために、Gitは`reflog`を用意している。これは、HEADがどこを指してきたかの履歴だ。
reflogを確認せよ。消したはずのコミットへのポインタが残っているはずだ
git reflog
`git prune`でオブジェクトを削除する前に、このreflogをクリアしないと、Gitは「まだ必要かもしれない」と判断してオブジェクトを温存する。これが多くの解説記事で「なぜか容量が減らない」と嘆かれる理由だ。
—
3. 「完全駆除」のステップバイステップ
以下の手順は、リポジトリの「歴史を書き換える」破壊的な行為を含む。実行前に必ずバックアップ(物理的なディレクトリコピー)を取ること。
Step 1: reflogの焼き払い
まず、過去の足跡を強制的に消去する。
30日以上前のreflogを即座に破棄(実戦では expire –now を使う)
git reflog expire –expire=now –all
Step 2: 到達不能オブジェクトの特定と削除
ここでようやく、誰からも参照されていない「ゾンビ」に死刑宣告を下す。
到達不能なオブジェクトをパックファイルから分離
git gc –prune=now –aggressive
`–aggressive`オプションは、オブジェクトの圧縮を限界まで行う。CI環境のクリーンアップなどでは必須のフラグだ。
—
4. 現場のテックリードが導入すべき「神設定・ハック」
生産性を上げるのは「掃除」だけではない。日々の開発体験を劇的に変える設定を共有する。
おすすめのGitエイリアス(`.gitconfig`)
タイピング回数を減らすのが、最も速い最適化だ。
[alias]
# 直近のブランチ操作を高速化
br = branch
co = checkout
# 孤立オブジェクトを視覚化(今何が消せる状態か)
lost = fsck –lost-found
# 変更をスタッシュしてすぐ戻る最強のワンライナー
save = stash push -m
`.gitconfig` の共有化ルール
チームの生産性を揃えるには、リポジトリ直下に `.gitconfig.local` を置き、`include` で読み込ませるのがベストプラクティスだ。
.gitconfig
[include]
path = .gitconfig.local
—
5. 巨大バイナリの罠:LFSへの移行
もしリポジトリが巨大な原因が「バイナリファイル」なら、`git-prune`では解決しない。Git LFS (Large File Storage) を導入せよ。
1. `git lfs install`
2. `git lfs track “.psd”` (デザインデータなどを追跡対象外にする)
3. `git filter-repo`(かつて `git filter-branch` で行っていた処理を、現在はこれで行うのが高速で安全)を用いて、過去の履歴からバイナリを削除し、LFSへ移行させる。
—
最後に:Gitは「道具」であって「アーカイブ」ではない
Gitはコードの変更を管理するツールだ。数年前の、誰も触っていない巨大なアセットがリポジトリに残っていることで、新人のクローン時間が10分伸びる。その10分×人数分の損失を、テックリードなら計算できるはずだ。
今日から「不要なブランチは即座に消す」「定期的に`git gc`を走らせる」という文化をチームに定着させろ。
「クリーンなリポジトリは、クリーンなコードを生む」。
これが、現場を渡り歩いてきた私の結論だ。さあ、ターミナルを開いて、ゾンビたちを葬り去りに行こう。