概要
本記事は rebase で運用するリポジトリでコミットがぐちゃぐちゃなってしまい、コンフリクト対応に苦労した自身の対応記録になります。
上記を回避するには、コミットの整理が有効です。
コミットを整理するには git rebase -i
が使えます。ローカルブランチでのコミットは細かくしても OK ですが、リモートへ push する前にコミットを整理する際に使うと良いです。理由は、整理せずにコミットすると、不用意に触ってしまったファイルなどがあるとコンフリクトのリスクが高まり開発効率が落ちるためです。
背景
まずは rebase をうまく使いこなせていなかったことで、下記のようなブランチになってしまった。
そもそもどうすべきだったか
git rebase
の意味を把握するrebase は自分の変更を後ろに足すという流れなので、複数ファイルを触ったようなコミットがあるとコンフリクトが発生しやすくなります。よって、後述のコミットの整理を行うことでそうした履歴を残さないのが重要
https://www.sejuku.net/blog/wp-content/uploads/2018/09/git-rebase3-640x360.png
コミットを整理する
上述の通り、コードが固まるまでは、コミットを細かくするのは別に構わないですが、ある程度形になってきたら、コミットの整理が必要。上述の通り、コンフリクト発生予防が期待できるためです。
コミットをまとめるのは、
git rebase -i <ひとまとめにする地点の一つ前のコミットID>
で実現できる。下記の例だと、ブランチAの前の『開始地点』コミットを指定する。https://www.sejuku.net/blog/wp-content/uploads/2018/09/git-rebase6-640x360.png
ローカルブランチからリモートへ上げる前に必ずコミットを整理したい。
で、ぐちゃぐちゃになった時にどうするか?
対応方法は大きく2つある。いずれも新規ブランチを main から立てるところは変わらない。その後の作業は次のパターンがある。
変更コード内容を手作業で貼っていく
Github なら『Files changed』タブの内容を見ながら、変更コードをペタペタと新しいブランチに貼っていく。この方法は、後述の
cherry-pick
を知らなくてもできるので、パッとできる方法で手軽だと思います。cherry-pick で対応
必要なコミットを指定して取り込んでいく。
git cherry-pick <取り込むコミットID>
でコミットを取り込むことができる。cherry-pick
という git の機能を活用するので、少し慣れた人向けだと思います。操作の流れは下記のような感じかなと思います。- リモートの main ブランチから新しいローカルブランチBを立る
- ぐちゃぐちゃになったブランチAから必要なコミットを
git cherry-pick <commitID>
で取り込む - 最後に、
git rebase -i
でコミットを整理する
上記の流れを図示してみると下記のような感じ。
上記のようにすることで、ぐちゃぐちゃになったコミットを整理できるようになる。コミットが綺麗にできたら git push origin <ブランチ名> --force-with-lease
でプッシュしてあげれば良い。
実際にやってみる
- まずはリモートリポジトリの main ブランチから新しいブランチを立てる。
必要なトピックを
git cherry-pick <取り込むコミットID>
で抜き取る元々70個あったコミット(自身のコミット以外が混ざっている状態)から、自身の変更分のみを抽出し、下記のような感じにしました。
cherry-pick
だけで対応できていない部分の修正FBC アプリの場合、main が毎週更新されるので、対応できていない部分が発見されたら対応する(今回に限らず、いつも通りの作業)
git rebase -i
でコミットを意味のある単位にまとめる今回は、main ブランチのコミットを開始地点として指定して、
git rebase -i
を実行します。すると、次のような画面になる。上記の
pick
となっている部分はコミットを残す部分で、まとめたいコミット部分はsquash
にしていく。ポイントは古いコミットにまとめていくので、まとめる側の古い側をsquash
にする。今回は次のように修正。次にコミットメッセージを修正していく。上記では、コミットを3つのコミットにまとめるので、メッセージも3回更新する。更新完了すると次のような感じになる。
コミットがまとまったかを
git log --graph
で確認してみます。十数個あったコミットが1つにまとまりました🙌
ここ2週間くらい、rebase
のコンフリクトに苦しみましたが、そのおかげで理解が深まった気がします。今後は無闇にリモートから rebase
せずにまずはローカルを整理してから対応をしていこうと思いました😅
Git 操作でやらかした場合
git reflog
が使える。上記を実施している際にも、何度も git 操作をやり直すことになったんですが、git reflog
がめちゃめちゃ優秀でした👀今後も何かあった時には、頼ろうと思いました。