🛠️

revertのrevert|ブランチを過去の状態に戻して、戻した作業に追加の作業をした後、またマージし直す

2022/03/22に公開

ここに、マージ先ブランチマージ元ブランチがある。
マージ元ブランチの作業が終わり、マージ先ブランチにマージした。
図解: マージ元ブランチには3つのコミットがあり、古いコミットから順にA、B、Cと表現されている。マージ先ブランチに対して、マージ元ブランチをマージした結果、マージ先ブランチにはマージしたことを示すコミットが作られる。そのコミットをDと表現している。
しかし、マージした後に、不具合が見つかってしまった。
一度過去の状態に戻して、不具合を修正したら再度マージし直そう。

まず、ブランチを過去の状態に戻すためにRevertする。

git revert -m 1 D 
※DはコミットIDを表す。ここでは、図のコミットDのIDをDとする。

マージコミットをRevertする時には、 -m 1 というオプションが必要になる。何をしているのかというと、マージ先ブランチの1個前なのか、マージ元ブランチの1個前なのか、どちらの状態にしたいのかを選んでいる。
今回はマージ先ブランチの1個前の状態にしたいため 1 を記述する。

これで、マージする前の状態に戻すことができた。

次に、マージ元ブランチで不具合の修正をしていく。
FとGの作業をして不具合を修正した。

もう一度マージしよう。
図解: マージ先ブランチに対して、マージ元ブランチをマージした結果、差分が思った通りに表示されない様子。マージ先ブランチでは、Revertが行われ、Dのコミットを打ち消すEというコミットが作られている。一方、マージ元ブランチでは、マージ先ブランチのRevert後に、不具合を修正した2つのF、Gというコミットが作られている。
・・・ん?差分がFとGの作業しかないんだけど。
AとBとCの作業も差分として表示されないとおかしい。

おかしいと感じるかもしれないが、AとBとCの作業は表示されないのが正しい。
なぜなら、マージ先ブランチには、すでにAとBとCの作業が存在しているからだ。

Revertで打ち消してはいるが、AとBとCの作業を相殺するコミットを作って上書きしているだけであって、AとBとCの作業はずっとマージ先コミットに残り続ける。
1つのブランチに全く同じコミットが複数存在することはできないので、もう一生、AとBとCの作業そのものを新しくマージすることはできない。

・・・え、じゃあAとBとCの作業どうするんだ。。

この問題を解決するためには、RevertをRevertする。
まずは、マージ先ブランチをマージ元ブランチに逆マージする。これで、マージ元ブランチにもRevertのコミットログがある状態になる。この状態で、Revertのコミットに対してRevertする。

git revert E
※EはコミットIDを表す。ここでは、図のコミットEのIDをEとする。

AとBとCを打ち消した状態になっているのを、AとBとCを打ち消した状態を打ち消した状態にする。そうすることで、AとBとCの作業を復活させることができる。

これで、AとBとCの差分も表示されるようになる。
図解: マージ元ブランチでRevertコミットに対して、さらにRevertを行ってからマージ先ブランチにマージすることで差分が思った通りに表示される様子。マージ元ブランチには、マージ先ブランチを取り込んだHというコミットと、RevertコミットをRevertしたIというコミットが作られている。その後マージ先ブランチに対してマージ元ブランチをマージし、マージ先ブランチにJというコミットが作られている。

反映したい作業の全てを差分として確認することができた。
これで再度マージすることができる。

※もし僕の理解が間違ってる箇所があった場合は教えてください🙇‍♂️

Discussion