blog.risouf.net

Git で merge commit を revert したあと、再度 merge したい

Git の merge は、「2つのブランチの共通の親を探し、そこから merge されるブランチのコミットを順に merge するブランチに適用」していくものだ。

では、次のようなときどうするか。

ケース

とあるコミットの歴史

とあるコミットの歴史

上の画像において、それぞれのコミットは以下の通りである。

上記グラフができるまでの流れは、

  1. マージを行う(Mコミットが作られる)
  2. 先のマージはまだ早かったと気づき、 revert する(Rコミットが作られる)
  3. しばらく経ち、マージしても良くなったので再度マージを行う(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

Tweet $B$3$N%(%s%H%j!<$r$O$F$J%V%C%/%^!<%/$KDI2C(B