git rebase –onto で解決できる 3つのシナリオ


よくある3つの困ったシナリオ

Gitを使っていると、意図せずコミット履歴が複雑になってしまうことがあります。これから紹介するのは、多くの開発者が一度は経験するであろう代表的なシナリオです。

シナリオ1: 他のフィーチャーブランチから派生してしまった

本来は最新の main ブランチから切るべき自分の作業ブランチ (my-feature) を、うっかり同僚が開発中の dev-feature から派生させてしまったケース。このままでは、Pull Requestに無関係なコミットが含まれてしまいます。

問題の状況

シナリオ2: 一つのブランチに複数の変更が混在してしまった

一つのブランチ (work-branch) で作業中、コミットCとDが実は別の機能 (new-idea) であることに気づいたケース。この2つのコミットだけを、新しいブランチとしてきれいに分離したい状況です。

問題の状況

シナリオ3: 古いブランチから新しい作業を始めてしまった

数ヶ月前に作ったまま放置していた old-feature ブランチ上で、新しい作業 (new-work) を始めてしまったケース。main ブランチはその間に大きく進んでおり、古い履歴の上に新しいコミットが乗ってしまっています。

問題の状況

これらの悩みはすべて git rebase --onto で解決できます。

解決の鍵: git rebase --onto とは?

git rebase --onto は、「どのコミットから(from)」「どのコミットまで(to)を」「どこへ(onto)」移動させるかを正確に指定できる、非常に強力なリベースコマンドです。

コマンドの基本構文

この3つの引数を理解することが、このコマンドを使いこなす鍵となります。

実践:シナリオ別コマンド解説

シナリオ1: 他のフィーチャーブランチから派生

それでは、最も一般的な「シナリオ1: 他のフィーチャーブランチから派生してしまった」ケースを例に、具体的な使い方を見ていきましょう。

やりたいこと: my-feature ブランチを、dev-feature からではなく main から派生した形に付け替える。

コマンド解説

このコマンドひとつで、Gitは以下のように履歴を再構築してくれます。

リベース後の理想的な状況

my-feature ブランチのコミット(B’, C’)が main の上にきれいに移動し、dev-feature とは無関係になりました。

シナリオ2: ブランチから一部のコミットを分離する

やりたいこと: work-branch の中のコミットCとDを、new-idea ブランチとして main から派生させる。この場合は、コミットIDを直接使います。

これにより、new-idea ブランチにはコミットCとDだけが main の上に再配置されます。

シナリオ3: 古い派生元から最新のベースへ移動

やりたいこと: new-work ブランチを、古い old-feature の上から、最新の main の上へ移動させる。

コマンドの形はシナリオ1と全く同じです。rebase --onto は、ブランチ間の距離がどれだけ離れていても問題なく動作します。

安全に実行するための注意点とTips

リモートリポジトリへのプッシュ

リベースはローカルのコミット履歴を書き換えます。リベース後にリモートへプッシュする際は、チームメンバーに影響を与える git push --force は避け、より安全な --force-with-lease を使いましょう。

リベース中にコンフリクトが発生した場合

リベースはコミットを一つずつ再適用していくため、途中でコンフフリクトが発生することがあります。その際は慌てず、以下の手順で対処しましょう。

  1. コンフリクトしたファイルを修正する: エディタでファイルを開き、<<<<<<<, =======, >>>>>>> のマーカーを参考に、コードを正しい状態に修正します。
  2. 修正したファイルをステージングする:
  3. リベースを続行する:

もし、コンフリクト解決が困難でリベース作業を中断したくなった場合は、以下のコマンドでリベース開始前の状態に戻せます。

総括

git rebase --onto は、一見すると複雑に感じるかもしれませんが、「どこからどこまでを、どこへ」という概念を理解すれば、Gitの歴史を自由自在に整理できる魔法の杖となります。

今回ご紹介したシナリオに心当たりがあれば、ぜひこのコマンドを試してみてください。ただし、共有済みのブランチで履歴を書き換える際は、チームとコミュニケーションを取ることを忘れないようにしましょう。