Git で merge commit を revert したあと、再度 merge したい
2014-05-08
Git の merge は、「2つのブランチの共通の親を探し、そこから merge されるブランチのコミットを順に merge するブランチに適用」していくものだ。
では、次のようなときどうするか。
ケース
上の画像において、それぞれのコミットは以下の通りである。
- S:分岐元のコミット
- M, G:マージコミット
- R:マージコミット(M)の revert コミット
- A, B, C, D:通常のコミット
上記グラフができるまでの流れは、
- マージを行う(Mコミットが作られる)
- 先のマージはまだ早かったと気づき、 revert する(Rコミットが作られる)
- しばらく経ち、マージしても良くなったので再度マージを行う(Gコミットが作られる)
という感じだ。
さて、このときGコミットには、A、B、C、Dの4つのコミットが適用されていて欲しい。
しかし実際には、CとDの2つだけしか適用されない。
なぜなら、Gのマージコミットの共通はBコミットだからだ。
そしてBコミットはその後Rコミットで revert されている。
もちろん、CとDの2つだけが適用されれば良い場合は何の問題もない。
しかし、AとBも含まれてほしい場合はどうすれば良いか。
解決方法
Twitter でこの疑問を呟いたところ、 @kana1さんに解法を教えていただいた。
@risou https://t.co/Pq9nfnKbeM まさにこれに解説されてる通りのシチュエーションですね。risouさんの図のRはgit revert -m1 Mで作られたと思います。Dをマージする時はgit revert Rしてからgit merge Dだそうですよ。
— Kana Natsuno (@kana1) April 25, 2014
どうやら2008年に同じ問題に遭遇し、解法が提供されるまでの一連のやりとりがあったようだ。
簡単に説明すると、Gのマージを行う前に revert コミットを revert すれば良い。
わかってしまえば簡単なことだった。
つくづく Git は良くできていると思わされたのだった。
# そもそもの問題として、より良いブランチの運用方法があるような気はしているが、それについては現場で模索中である。
2014-05-08 02:15:56.116753 JST