k-tokitoh

2019-09-04

gitでrevertしたら再revertが必要な例とその理由

git revert で注意すべきこと - Qiita

こちらの記事を読んで、「何が起きるか」はわかったけど「なぜこうなるか」がすぐに分からなかったのでメモ。

具体例

以下の例を考える。

* 6589fe9 (HEAD -> master) Revert "Merge branch 'dev'"
* c7e7528 Merge branch 'dev'
|\
| * 30f185a (dev) added b.txt
* | 5169671 added c.txt
|/
* 18f28e9 added a.txt

問題が発生するパターン

* 436c043 (HEAD -> master) Merge branch 'dev'
|\
| * ddf8924 (dev) added d.txt
* | 6589fe9 Revert "Merge branch 'dev'"
* | c7e7528 Merge branch 'dev'
|\|
| * 30f185a added b.txt
* | 5169671 added c.txt
|/
* 18f28e9 added a.txt

ここでマージ後の master がどうなっているかというと…

% git checkout master
% ls
a.txt   c.txt   d.txt

当初 dev ブランチで追加した b.txt が見当たらない。

問題が発生する理由

問題を回避するやり方

いずれにせよ revert 以前の内容が必要なら、revert を revert すべし。

dev ブランチをそのまま伸ばす

* 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

ブランチを切り直す

* ea16e7a (HEAD -> master) Merge branch 'dev2'
|\
| * a87d323 (dev2) added d.txt
| * 98c5d6f Revert "Revert "Merge branch 'dev'""
|/
* 6589fe9 Revert "Merge branch 'dev'"
* c7e7528 Merge branch 'dev'
|\
| * 30f185a (dev) 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