はじめに
最近git rebase後に発生したコンフリクトをビビりながら解消した。
もう二度と冷や汗をかかないようにするべく、備忘録がてら再現してみる。
手順①:初期状態の作成
まずはrebase後にコンフリクトを発生させるために図の状態になるようコミットを作成する。
※hoge・fugaはブランチ名、[A-E] はコミットを示している。
この時、hogeのCコミットとfugaのDコミットの間でコンフリクトが発生するようにする。
手順②:rebaseの実行
手順①で作成した状態から、以下のイメージになるようrebaseコマンドを実行する。
※fugaブランチ上で git rebase hoge
この時コンフリクトが発生すればOK(手順①でそうなるようにしたため)。
この発生したコンフリクトを解消する時に、fugaのEコミットの内容を上書きする形で修正してほしい。すると再度コンフリクトが発生するはず。
なぜならrebaseとは「派生先ブランチの各コミットが、既に適用されている直前のコミットに対して順番に適用される動き」だからである。筆者はここが理解できておらず解消するときに焦ることとなった。
分かりやすくするため、この説明に今回のrebaseの流れを当てはめてみる。
まず初めに、rebase先はhogeブランチのCコミットなので「既に適用されている直前のコミット」はCコミットとなる。
「派生先ブランチ(=fuga)の各コミット」にはfugaのDとEが該当するが、「順番に適用される」ので今回はfugaブランチのDコミットになる。
そしてC・D間のコンフリクトを解消したもの(D'コミット)がCコミットの直後に適用される。
続いて2回目の処理だ。
先ほどと同様にrebaseの説明に各コミットを当てはめると
「既に適用されている直前のコミット = 先ほど適用したD'コミット」
「順番に適用される派生先ブランチの各コミット = fugaのEコミット(Dは1回目に適用済み)」
となる。
D'コミットはEコミットとコンフリクトが発生するようにしたので、これを解決したもの(E'コミット)がD'コミットの直後に適用される。
以上で今回のrebase処理は完了となる。
まとめ
結局、今回の状況で焦ってしまった理由は、rebaseの知識が足りないこともあるがmergeばかり使用していたからだと思う。
mergeであれば各ブランチの最新のコミット同士で比較・統合するので、rebaseのように順番に適用されることがなくコンフリクトが発生したとしても1回で抑えられる。
このせいで「コンフリクト=1回しか起きないもの」と思い込み、rebase時に発生した複数回のコンフリクトにビビってしまった。
実務の時に焦らないためにも、やっぱり勉強って大事だなと痛感した出来事だった。