2019-09-04
gitでrevertしたら再revertが必要な例とその理由
こちらの記事を読んで、「何が起きるか」はわかったけど「なぜこうなるか」がすぐに分からなかったのでメモ。
具体例
以下の例を考える。
master ブランチから dev ブランチを切った。
dev ブランチで b.txt を追加してコミットを積んだ。
master ブランチで c.txt を追加してコミットを積んだ。
master ブランチに dev ブランチをマージした。
dev ブランチでの変更点に不具合があったことが判明し、master で dev のマージコミットを revert した。
問題が発生するパターン
dev ブランチにパッチを当てて(d.txt を追加して)コミットを積んだ
dev ブランチを再度 master にマージした
ここでマージ後の master がどうなっているかというと…
% git checkout master % ls a.txt c.txt d.txt
当初 dev ブランチで追加した b.txt が見当たらない。
問題が発生する理由
- 上記の commit 1 と commit 2 をマージするときに、マージベースは commit 3 となる。
- commit 3 から commit 1 にかけての差分は「d.txt を追加した」こと
- commit 3 から commit 2 にかけての差分は「なし」(b.txt が追加され、削除された)
- commit 3 では a.txt, b.txt が存在したので、それに上記 2 つの差分を足して実現するのは、a.txt, b.txt, d.txt が存在する状態
問題を回避するやり方
いずれにせよ revert 以前の内容が必要なら、revert を revert すべし。
dev ブランチをそのまま伸ばす
dev ブランチに master をマージする
dev ブランチで revert を revert する
dev ブランチにパッチを当てて(d.txt を追加して)コミットを積む
dev ブランチを再度 master にマージする
3a746ec
(HEAD -> master) Merge branch ‘dev’ |\ |e3cf889
(dev) added d.txt |498e552
Revert “Revert “Merge branch ‘dev’"" | *c440eb6
Merge branch ‘master’ into dev | |\ | |/ |/|- |
6589fe9
Revert “Merge branch ‘dev’” - |
c7e7528
Merge branch ‘dev’ |\ \ | |/ | *30f185a
added b.txt - |
5169671
added c.txt |/ 18f28e9
added a.txt
こうすれば、当初 dev ブランチで作成した b.txt も最終的に master ブランチに残る。
% git checkout master % ls a.txt b.txt c.txt d.txt
ブランチを切り直す
master ブランチから dev2 ブランチを切り直す
dev2 ブランチで revert を revert する
dev2 ブランチにパッチを当てて(d.txt を追加して)コミットを積む
dev2 ブランチを master にマージする
この方法でも、当初 dev ブランチで作成した b.txt が最終的に master ブランチに残る。
% git checkout master % ls a.txt b.txt c.txt d.txt