モノレポからの脱出:git-filter-repoによる履歴を維持した「外科手術」の極意
モノレポは開発の初期段階では強力な武器だが、組織がスケールし、境界条件が複雑化するにつれ、それは「技術的負債の墓場」と化す。特定プロジェクトを独立させる際、`git-filter-branch` を使おうとしているなら、今すぐブラウザを閉じろ。あれは歴史の遺物であり、リポジトリのインデックスを破壊する時限爆弾だ。
今回は、Gitの深淵を知るエンジニアのために、`git-filter-repo` を用いた「特定のサブディレクトリを履歴ごと切り出す」究極の自動化戦略を伝授する。
—
なぜ `git-filter-repo` なのか:内部アーキテクチャの視点
`git-filter-repo` は、単なるラッパーではない。Gitの内部フォーマットである `fast-export` ストリームを直接操作し、Pythonの強力な最適化エンジンで履歴を再構築する。
- メモリ効率: 大規模リポジトリでもストリーム処理により、メモリを食い潰さずに巨大な履歴を処理できる。
- 整合性: `git-filter-branch` が抱えていた「マージコミットの破損」「コミットIDの不整合」といった問題を、設計段階で排除している。
- 速度: 処理速度は `git-filter-branch` の数倍から数十倍。数ギガバイトの履歴も数分で焼き直せる。
—
現場で震える「完全自動化スクリプト」
単にコマンドを叩くだけではプロとは呼べない。CIパイプラインやマイグレーションツールとして組み込むための、冪等性を担保した自動化スクリプトを提示する。
!/usr/bin/env bash
git-extract.sh: 特定ディレクトリを抽出してクリーンなリポジトリを作成する
set -euo pipefail
TARGET_DIR=$1
REPO_NAME=$(basename “$TARGET_DIR”)
OUTPUT_DIR=”../${REPO_NAME}-extracted”
1. 破壊的変更のため、必ずクローンから作業する
元のリポジトリを汚染しないのがプロの鉄則
git clone –mirror . “${OUTPUT_DIR}”
cd “${OUTPUT_DIR}”
2. git-filter-repoによる外科手術
–path で対象ディレクトリのみを指定
–force は再構築の過程で必須
git filter-repo –path “${TARGET_DIR}/” –force
3. 内部最適化:不要になったオブジェクトの完全削除
git reflog expire –expire=now –all
git gc –prune=now –aggressive
echo “Extraction complete: ${OUTPUT_DIR}”
—
極限の最適化:エンジニアが知るべき「魂のハック」
1. メモリ不足(OOM)との戦い
数千万行の履歴を持つリポジトリを処理する場合、PythonのGCが追いつかないことがある。環境変数 `PYTHONUNBUFFERED=1` を設定し、`–analyze` オプションで先にデータ分布を把握せよ。また、一時ディレクトリをRAMディスク (`/dev/shm`) にマウントして作業することで、I/Oボトルネックを解消できる。
2. 依存関係の解決(マッピングの魔術)
`–path-rename` を活用せよ。例えば、`projects/service-a/` をルートに移動させたい場合、以下のようにコマンドを叩く。
git filter-repo –path projects/service-a/ –path-rename projects/service-a/:
このコマンドは、対象ディレクトリ内の全ファイルをルートディレクトリに再配置しつつ、過去の全てのコミット履歴におけるパスを書き換える。これを手動で行えば、数日の工数が飛ぶ。
3. CI/CDパイプラインとの統合
このスクリプトをGitHub ActionsやGitLab CIに組み込む際は、「疎結合なクローン」を前提とすること。
- キャッシュ戦略: `git-filter-repo` は再実行が容易ではないため、キャッシュは使用せず、毎回 fresh clone からパイプラインを回す。
- 検証: 切り出し後、`git rev-list –count HEAD` でコミット数を比較し、`git diff HEAD` で親リポジトリとの一致を確認する「自動検証ステップ」を必ずパイプラインの最後に加えること。
—
伝説のアーキテクトからの助言
リポジトリの分離は、単なるコードの移動ではない。「組織の権限境界の再定義」だ。
`git-filter-repo` は極めて強力だが、歴史を書き換える行為は不可逆だ。実行前には必ず、対象リポジトリの全ブランチと全タグをバックアップし、チーム全員に作業を停止させろ。歴史を改ざんすることは、過去を消し去ることと同義である。
このツールを使いこなしたとき、君は「モノレポという名の檻」から自由になる。だが、忘れるな。自由には責任が伴う。切り出したリポジトリの依存関係管理、CI/CDの再構築、そしてレガシーコードの継承。それら全てを設計し直す覚悟がある者だけが、この刃を振るう権利を持つ。
さあ、リポジトリを外科手術台に乗せろ。準備はいいか。