モノレポの呪縛を解き放て:`git-filter-repo`による究極のレポジトリ分離戦略
大規模モノレポを運用していると、ある時点で必ず直面する壁がある。「特定のディレクトリだけを切り出して、独立したプロダクトとして運用したい」という要求だ。
かつて我々は`git-filter-branch`という名の地獄に足を踏み入れていた。遅く、壊れやすく、そして何より歴史を改竄するたびにgitの内部構造を破壊するリスクを孕んでいたからだ。だが、今は違う。`git-filter-repo`こそが、その歴史的負債を清算し、開発スピードを劇的に加速させるための唯一の正解だ。
今日は、単なるツールの使い方ではなく、テックリードとして現場の生産性を極限まで引き上げるための「分離戦略」を伝授する。
—
1. なぜ`git-filter-repo`なのか?
`git-filter-branch`はシェルスクリプトをループさせるような低効率な代物だが、`git-filter-repo`はPythonで書かれ、Gitの内部データベース(fast-import/export)を直接操作する。
- 圧倒的な速度: 数GBのレポジトリでも数分で終わる。
- 安全性: 明示的なオプションなしでは操作できない設計になっており、破壊的変更に対するガードレールが優秀。
- クリーンな履歴: 不要なゴミ(.gitディレクトリの肥大化の原因となるBlob)を完璧に排除する。
—
2. 特定サブディレクトリ抽出の完全自動化スクリプト
手作業でコマンドを打つのはエンジニアの恥だ。以下の自動化スクリプトをプロジェクトの`scripts/`ディレクトリに格納し、チーム全員が同じ精度で分離作業を行えるようにせよ。
!/bin/bash
extract_repo.sh
使用法: ./extract_repo.sh <対象ディレクトリ名> <出力先ディレクトリ>
TARGET_DIR=$1
OUTPUT_DIR=$2
if [ -z “$TARGET_DIR” ] || [ -z “$OUTPUT_DIR” ]; then
echo “Usage: ./extract_repo.sh
exit 1
fi
1. 既存リポジトリのクローン(念のため –no-local でフルコピー)
git clone –no-local . “$OUTPUT_DIR”
cd “$OUTPUT_DIR”
2. git-filter-repo でサブディレクトリ以外を全て削除
–path で対象を指定し、それ以外を履歴から抹消する
git filter-repo –path “$TARGET_DIR/”
3. 指定ディレクトリをルートに移動(オプション)
これを実行することで、サブディレクトリの中身が直下に展開される
git filter-repo –subdirectory-filter “$TARGET_DIR”
echo “Success: $TARGET_DIR が $OUTPUT_DIR に独立しました。”
—
3. 現場で差がつく「神」設定とハック
Gitの運用において、ツール以上に重要なのが「設定の共有」だ。チーム全員が同じ土俵で戦うために、以下の設定を`gitconfig`に刻み込め。
A. 必須のキーボードショートカット (alias)
`git`のコマンド入力を極限まで減らす。これが開発スピードの正体だ。
[alias]
# 直近のブランチへの素早い移動
sw = checkout
# ログをツリー状で見やすく(必須)
lg = log –graph –pretty=format:’%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset’ –abbrev-commit
# フィルタリング後のクリーンアップを簡略化
f-repo = !python3 -m git_filter_repo
B. チーム開発における設定の共有化ルール
設定ファイル(`.gitconfig`)をリポジトリ内に`config/gitconfig`として含め、以下のように読み込ませるのがベストプラクティスだ。
ローカルの .git/config に追加
[include]
path = ../config/gitconfig
このファイルに `[push] default = simple` や `[pull] rebase = true` といった「強制的な開発フロー(Rebase前提)」を記述することで、マージコミットによる履歴の汚染を未然に防ぐ。
—
4. テックリードからの提言:分離後の運用
リポジトリを分離した後に最も重要なのは「依存関係の管理」だ。
分離したリポジトリが元のモノレポの共通ライブラリを必要とする場合、`git submodule`は極力避けるべきだ。あれは悪夢の温床になる。代わりに、「パッケージマネージャによる外部参照(npm, pip, go mod等)」または「CI/CDパイプラインによるアーティファクト配布」に切り替えるのが現代の最適解だ。
推奨されるディレクトリ構成 (CI用YAML例)
分離後のCI設定は、モノレポ時代の複雑なPathフィルタリングから解放され、以下の様にシンプルに保てる。
.github/workflows/ci.yml
name: CI for Isolated Repo
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Environment
run: |
# 独立したリポジトリなので、設定はシンプルに完結する
make install
- name: Run Tests
run: make test
最後に
モノレポを分離することは、単に物理的に分けることではない。「チームが自律的にデプロイできる範囲を定義する」という、DevOpsの究極の設計判断だ。
`git-filter-repo`はそのための最強のメスである。迷わず使いこなせ。そして、複雑な履歴の呪縛からプロジェクトを解放し、コードに魂を込める時間を取り戻してほしい。質問があればいつでも聞く。我々の仕事は、コードを書くことではなく、コードが流れる仕組みを完璧に作ることなのだから。