「Merge branch 'develop' into feature/A」... プルリクエストのレビュー時に、このような意味のないマージコミットが数十個並んでいるのを見ると頭痛がします。大規模なチーム開発において、Gitの履歴は単なるログではなく、バグ追跡のための「証拠物件」です。最近関わったプロジェクトでは、コミットログがスパゲッティ状態だったために、重大なリグレッション(回帰バグ)の特定に3日を要しました。本稿では、開発フローを整理し、デバッグ時間を劇的に短縮するために私が現場で強制している rebase、cherry-pick、bisect の運用ルールを共有します。
Rebase: ノイズを排除し、履歴を「物語」にする
多くの現場で git merge がデフォルトで使われていますが、機能ブランチの取り込みにおいてマージコミットはノイズになりがちです。履歴を一直線(リニア)に保つことで、後述する bisect の効率が最大化されます。
origin/main など、他人が参照している共有ブランチに対して rebase を行い、履歴を書き換えてはいけません。これはチーム全体のレポジトリを破壊します。rebase はあくまで「ローカル作業中」または「マージ前の機能ブランチ」に対して行います。
開発中、「WIP(作業中)」コミットが乱立した場合、対話的リベース(Interactive Rebase)を使用して、論理的に意味のある単位に圧縮(Squash)します。
// 直近の5つのコミットを整理する
git rebase -i HEAD~5
// エディタが開くので、以下のように編集する
// pick 1234567 feat: 認証機能のベース作成
// squash 2345678 fix: 誤字修正 <-- 前のコミットに統合される
// squash 3456789 wip: ロジック調整 <-- 前のコミットに統合される
Cherry-pick: 外科手術的なパッチ適用
本番環境(v1.0)で緊急のバグが見つかり、開発環境(v2.0-dev)では既に修正されているケースを考えます。ブランチ全体をマージすると未完成のv2.0機能まで本番に入ってしまうため、特定のコミットだけを「つまみ食い」して適用する必要があります。
-x オプションを付けることを強く推奨します。これにより、コミットメッセージに「(cherry picked from commit ... )」というフッターが自動追加され、オリジナルのコミットとの追跡が可能になります。
// 特定のコミットハッシュ(修正パッチ)を現在のブランチに適用
// -x: オリジナルのコミットハッシュを記録
git cherry-pick -x a1b2c3d
// コンフリクトが発生した場合の対処フロー
// 1. ファイルを修正
// 2. git add <file>
// 3. git cherry-pick --continue
Bisect: 二分探索によるバグ特定
「昨日は動いていたのに、今日は動かない。間には100件のコミットがある」。この状況で一つずつチェックアウトして確認するのは非効率です。git bisect は二分探索アルゴリズムを用いて、バグが混入した正確なコミットを $O(\log N)$ の計算量で特定します。
// 1. 二分探索を開始
git bisect start
// 2. 現在の状態(バグあり)をマーク
git bisect bad
// 3. バグがなかった過去の時点(例えばv1.0タグ)をマーク
git bisect good v1.0
// --- Gitが自動的に中間のコミットをチェックアウトする ---
// 4. テスト実行(手動確認 または 自動テスト)
// 動作確認後、その結果をGitに教える
git bisect good // 問題なしの場合
// または
git bisect bad // バグ再現の場合
// 5. 犯人(コミット)が見つかるまで4を繰り返す
// 6. 終了して元のブランチに戻る
git bisect reset
手動探索 vs Git Bisect
以下は、1000件のコミット履歴からバグを特定するために必要なステップ数の比較です。リニア探索がいかに時間を浪費しているかが分かります。
| コミット数 | 手動確認 (線形探索) | Git Bisect (二分探索) | 時間節約効果 |
|---|---|---|---|
| 100 | 平均 50 ステップ | 約 7 ステップ | 約 7倍 |
| 1,000 | 平均 500 ステップ | 約 10 ステップ | 約 50倍 |
| 10,000 | 平均 5,000 ステップ | 約 14 ステップ | 約 350倍 |
Conclusion
Gitは単なるバックアップツールではありません。rebase で履歴を綺麗に保つことは、将来のデバッグ作業への投資です。そして、綺麗な履歴があれば git bisect は最大の効果を発揮します。まずは手元のローカルブランチの整理から始め、チーム全体で「追跡可能な履歴」を維持する文化を作ってください。
Post a Comment