rebaseでコミットをまとめる際、プチやらかし案件を引き起こしてしまいました。
「複数のコミットをまとめて反映するならpatchを使うと良い」とアドバイスを受けたのですが、ググってみたら、rebaseでまとめる方法が多く紹介されていました。
この2通りの方法の違いが分からず調べたので、自戒を込めて記録しようと思います。
そもそもの2通りの方法の概要
1. patchファイルを当てる方法
複数のコミットを1個の差分にまとめる方法
-
$ git diff -p <派生元ブランチ> <派生先ブランチ> > a.patch
2ブランチ間の差分をpatchファイルとして出力します。
※patchファイル名は任意です -
$ patch --dry-run -p1 < a.patch
ドライラン(テスト実行)で差分ファイルを確認します。 -
$ patch -p1 < a.patch
差分を確認後に実際に流し込むと、git add
の手前の状態になります。 - (+α)
$ git diff <派生元ブランチ> <派生先ブランチ> | patch -p1
このように、1行にまとめて一気に実行することもできます。
2. rebaseでまとめる方法
-
$ git rebase -i HEAD~(HEADから遡るコミット数)
vimが立ち上がるので、コミットメッセージやコミットの並び等を編集・保存する。 -
$ git push -f origin <branch>
強制プッシュは慎重に!! - ※rebase前のコミット履歴はpush済みで、rebase中にコンフリクトしたら次の手順を踏む。
-
$ git co --ours(--theirs)
片方のブランチの変更のみを一気に適用できない場合は、地道に編集するしか無い...? $ git add .
-
$ git rebase --continue
(コンフリクト解消後にrebaseを続行する)
→終わったら再度$ git push -f origin <branch>
-
参考サイト
- [Git] rebase コマンドで複数のコミットを 1 つにまとめる
- git rebase -i でコミットをまとめて履歴を綺麗にしよう!
- まとめた履歴を git push するときは、コンフリクトに注意。
- gitのコミットの歴史を改変する(git rebase) 1 / 2
- git rebaseでコミットを並べ替える
rebaseで少々やらかした話
何を失敗したのか
(@個人ブランチ) $ git merge develop
$ git rebase -i HEAD~xx でコミットをまとめる
$ git push -f origin <branch>
上記の手順を踏みました。何が起こるでしょうか?
・・・本ケースのように、まとめようとするコミットの間に、自分以外の人によるコミットが入っている場合は$ git rebase -i HEAD~xx
を使うのはまずかったのです。
$ git rebase -i HEAD~xx
でまとめると、他の人のコミットも付け直します。
この際に自分のコミットとしてまとめてしまうので、自分がコミットしたことになってしまいます。
自分の分のコミットだけを先にまとめてからdevelopブランチをマージする必要がありました。
(こちらを参照)
まとめ
全般
$ git push -f origin <branch>
は慎重に!!- 自分のコミットが分散している&他人のコミット入りのブランチをrebaseすると、
他人のコミットを自分のコミットとしてコミットし直してしまう。 - patchファイルを当てる方法
→個人ブランチのコミットログを改変するわけではないので、
個人ブランチの更新分を一括でdevelopブランチに適用する場合にしか使えない
=「個人ブランチにしかない差分を1つの差分としてまとめて抽出し、developブランチの先頭コミットにくっつける」イメージ
※この際、個人ブランチのコミットログは分散したままとなる。
対処法
- (このケースに陥ったら)このままマージするとまずい。
→もしやってしまった場合は、別のブランチ作り直す&自分の変更分をコミットから取り出すことで対処できる -
$ git rebase
だと枝の付け根を切り替えるというイメージ。 - 今回のように自分の変更が分散してしまっている場合:
別ブランチで切り直して、自分の分だけcherry-pick
するのが早いと思われる。
→git操作をミスった際の尻拭いとして使える... -
$ git reset
も使えると、間違えても修正が楽になる。
→オプションの--soft
,--hard
,--mixed
も意識できるとなお良し - マージ相手のブランチにcheckout
→他人のコミットを改ざんしてしまった個人ブランチをmerge
→pushせずに$ git reset HEAD^
で変更分だけ抽出することもできる
(大量にコンフリクトする可能性はあるが・・・)