はじめに
ブランチの途中にある不要なコミットを取り除きたいとき、git rebase -i でひとつずつ drop していました。git rebase --onto を使うと一発で解決できることがわかったので、備忘録を兼ねて記載しておきます。
やりたいこと
origin/develop から feature ブランチを切って作業していましたが、途中の3コミットはこのブランチには含めない(不要)ことになりました。
最新の 7e8f9a0b だけを origin/develop の直上に移植したい、というのがやりたいことです。
git rebase --onto の構文
git rebase --onto <新しい起点> <切り取り位置> <ブランチ>
| 引数 | 説明 |
|---|---|
<新しい起点> |
コミットを貼り付ける先 |
<切り取り位置> |
このコミット より後 が移植対象(このコミット自体は含まない) |
<ブランチ> |
移植対象の末端(ブランチ名) |
ポイントは<切り取り位置>の指定です。「このコミットまでは捨てて、次のコミットから持っていく」という境界線の役割を果たします。
<切り取り位置>にはブランチ名を指定する例が多いですが、コミット SHA を直接指定する方が「どのコミットまでを除外するのか」が明確になり、わかりやすいと感じました。本記事の例でも SHA で指定しています。
git rebase --onto origin/develop 3a4b5c6d feature
実行後:
不要なコミットが取り除かれ、7e8f9a0b が origin/develop の直上に移植されました。SHA で指定すると、ブランチの分岐点に関係なく性格に切り取り位置を制御できます。
ブランチ名で指定する例
<切り取り位置>にブランチ名を指定するパターンも記載します。
例えば、develop からfeature-A を切り、さらに feature-Aから feature-B を切って作業した状況を考えます。feature-B のコミットだけを develop の直上に移植したい場合:
git rebase --onto develop feature-A feature-B
結果:
feature-A の先端コミット(e9f0a1b2)が切り取り位置になるため、それ以降のコミットが develop に移植されます。ブランチ名で指定すると、そのブランチの最新コミットが自動的に切り取り位置として使われます。
通常の rebase との違い
git rebase origin/develop
ブランチ上の すべてのコミット を origin/develop の上に移植します。途中のコミットを間引くことはできません。
git rebase --onto origin/develop 3a4b5c6d feature
3a4b5c6d より後のコミットだけを origin/develop の上に移植します。
複数コミットを残す場合
残したいコミットが複数あっても同じコマンドで対応できます。
例えば、不要なコミットの後に3つのコミットが積まれている場合:
git rebase --onto origin/develop 3a4b5c6d feature
結果:
<切り取り位置> より後の すべてのコミット がまとめて移植されます。
注意点
- rebase はコミット履歴を書き換えるため、リモートに push 済みの場合は
git push -fが必要です - 共有ブランチで
push -fする場合は、他のメンバーに事前共有しましょう - コンフリクトが発生した場合は解消して
git rebase --continueで続行できます
まとめ
| やりたいこと | コマンド |
|---|---|
| 全コミットを移植 | git rebase origin/develop |
| 特定範囲のコミットだけ移植 | git rebase --onto <新しい起点> <切り取り位置> <ブランチ> |
git rebase --onto は「どこに」「どこから」「どこまで」を明示的に指定できるコマンドです。不要なコミットを取り除きたい時は、一度使ってみてください。