git revertの注意点
職場でgitを用いたコード管理を行なっていますが、ある時、マージしたのに変更点が反映されていない!という出来事がありました。これは「git revert」を使用していたことに原因がありました。今回は「git revert」について簡単な解説と使用する際の注意点に関して自分の考えをまとめたいと思います!
git revertとは
まず「git revert」とは一言で言えばコミットの内容を打ち消すコミットを作り出すというものです。打ち消すというのは指定したコミットの内容と逆の内容をコミットする→つまり変更点としてコミットを積み上げることになります。コミットを打ち消す方法としては「git reset」もありますが、リモートにpushしていても「git revert」は安心して使えることができるという点が良いですね。
「git revert」、「git reset」に関しては以下リンクが非常にわかりやすいです。
(連載全て読みましたが、わかりやすく非常にタメになりました)
参考: git revert
参考: git reset
「git revert」により発生した問題の解説
testブランチの変更点をコミットし、masterブランチにマージするとしましょう。下図は実際に今回起こった内容を図にしたものになっています。
+Xという変更点のコミットをtestで行い、masterにマージ①しています。その後masterで+Xのコミットを打ち消すリバート-Xを行なっています。次にtestで+Xの変更点とは異なるファイルの変更点を+Yとしてコミットしています。マージ②をすることで、最終的にtestとmasterのブランチのコードには違いが生じています。
私は初め、上図のように実行しても、testとmasterのコードは一緒になると思っていました。
なぜ私が勘違いをしたか、今回のような挙動がどうして起きるのかを続けて書いていきます。
誤った考え
私が勘違いした内容を下図に示します。下図では、勘違いしていた部分に関しては赤色で表示しています。
この時の私の思考を解説していきます。
masterブランチで-Xのリバートを実行しているから、masterでは+Xは打ち消しあって、消えた!マージ②をする時のtestとmasterのコードの差異は+Xと+Yだから、マージ②するとどちらもmasterに反映されて、最終的にtestとmasterのコードは一致するという考えでした。
誤った解釈としては、まずリバートはコミットを打ち消すコミットを作り、あくまでコミットの履歴を積み上げていっているということです。「git reset」のように完全に消えるような挙動ではないのです。そしてマージ②をする際、+Xは既にmasterに反映されている内容として認識されるので、+Yのみが反映されます。こちらは+XのコミットIDが変わらないから生じていると思っています。コミットは生成される時にコミットIDというものが作られます。マージ②を実行する際、masterには+XのコミットIDは既に一度反映されているので、マージ②では反映されないのだと思います。
この辺りはgitの各機能がどのように動作するのかをもっと正確に理解できたらなと思っています。
もう一度正しい挙動の図を下図に示しておきます。
まだわからない人のために
ここまでである程度理解してもらえたのではないかと思っているのですが、まだわからない人のための補足として下図を作ってみました。
-Xというリバートは+Xのコミットを打ち消すコミットということでした。+Xのファイルと+Yのファイルは干渉しないので、上図のようにマージ②を実行した後に-Xのコミットを実行してもやっていることは同じだと思いませんか?最終的にmasterで積み上げたコミットはここまでの内容と同様[+X、-X、+Y]の3つです。上図だと当然、testとmasterのコードは違ってくるというのはわかるはずです。
最後に
ここまで「git revert」について説明してきました。gitは非常に便利であり、エンジニアにとって必須なツールなので、より深くまで理解を含めていきたいと思います!
Discussion