質問: 本質問の最後に `revert`で問題に遭遇した例をネットからあげます。 私も過去に何度か `revert` でヒヤリハットがあってから、`revert`を極力使わないようにしているのですが(もう5年以上使ってないかも)、どういうときに問題が発生するのか(差分が出ない、変更したのに変更されない等)イマイチ把握できていません。なので、仕事場で仲間が `revert` を使おうとした場合、あまり説得力がある形で、`revert`の危険性を説明することができません。(危険なので使うのはやめようという意図はありません。問題が出るときもありましたと言いたいのですが、再現方法がわからないので、どういうときに危険なのか言えないのが困りごとです) 下記の例では「差分が出なくなる」とありますが、出るときもあるような気がしており、なかなか説得力がうまれません。 **質問** * `revert`すると必ずプルリクエスト時に差分が出なくなるものなのでしょうか? それとも差分が出るときもあるのでしょうか? * プルリクエスト時に差分が出たとしても、マージ後なぜかその差分が反映されていない現象に遭遇したこともあります 問題が起きたとき `revert`の`revert`をするとよいとありますが、開発が進んでいると`revert`の`revert`時にコンフリクトが起きて辛い思いをしたことがあります(とはいえ、`revert`した2,3日後なので、全員の記憶も残っており、なんとかなってしまうのですが)。 (過去の記憶で書いてしまっているので、今困っているわけではないですし、そもそも問題が起こる場合をうまく再現する方法がわかっていないので回答しづらいかもしれません。申し訳ありません) 遭遇する例としては、まだgitのことをよく知らない人(git 戻す等で検索して git reset, git revert等がひっかかるが区別がつかない)が、とにかくわからないが(といっても本人はわかってるつもり)`$ git revert なにかしらのコミット` して、プルリクエストを作ります。そのプルリクエストがマージされたあとに、新規ブランチをつくり、新しい機能を追加し、プルリクエストを作ると差分が出ないときがあるような気がしています。(この場合の`git revert` はコミットに慣れていないので、当人のコミットミスを戻したい場合が多く、`git revert`が適切でない場合が多い、`git commit --amend`や後述する`git reset --mixed`が適切であることの方が多い) 私自身は、自分のフィーチャーブランチで開発中に revert した場合、プルリクエストが取り込まれる前であれば git reset --mixed するなどして、revertをなかったことにするなどして、コミットをまとめてしまう(もしくは整理する)ことがあります。この場合、フィーチャーブランチ開発中の自分の実装ミス、もしくは開発中の仕様変更をrevetするので、コミット履歴としてrevertを残しておく有用性がないためです。 一度プルリクエストが通ったものに不備があったりする場合は GitHubのrevertボタンを押す等すると、過去に不備があったこと、そしてそれを打ち消したことがわかるので revertコミットを残しておくことは有用だと思います。歴史の書き換えもすでにみんなが見ている(みんなが起点にしている)のでやってはいけませんし。(しかし、差分が出なくなる, 変更したのに変更がなくなるパターンがわかってないのでなんか怖い。おそらくこの場合は問題は起こらない気がしてるが... 気がしているのではなく根拠を説明したいです) --- ここまで書いて思ったのですが、 まとめると gitに不慣れな人が、単純にコミットメッセージを作り間違えた、必要なファイルを`git add`し忘れていたといった単純な当人のコミットミスを修正するために `git revert`を使うと後々「差分が出なくなる」「変更したのに変更が反映されない」等の問題がおこる気がしているのですが、当人がもう`git revert`したくなっているので`git commit --amend`等の説明をしたいのですが、聞く耳を持っていない場合に強く説得したほうが良い気がするが、強い根拠を示せないということになりそうです。(`git commit --amend` のほうがキレイですよみたいな言い方にとどまってしまう。そしてもう `git push` してしまっていると `git push -f` をまだ不慣れな人に教えることになる...) (蛇足:当人が聞く耳をもたないのではなく、聞く余裕がないほどの納期プレッシャーを当人がかけられていることがある) revertで問題が発生している例 ----------------- Git マージコミットをrevert後に再度マージしたいけど差分が出ない時には - チョコパイを240こ食べたエンジニア > > Aブランチ⇒メインブランチへのマージ、再度プルリク作成! > > あれ、、、差分があるはずなのに出てこない汗 > > > GitHubでマージ済のプルリクをrevertした後に引き続きrevertされたブランチで作業を続行したい時 - Qiita > > GitHub上でプルリクをマージした後に、まだマージできる状態では無かったと気付きrevertする事ってありませんか? > > その後に問題になるのが、revertしたのはいいけど、引き続きそのrevertされたブランチで作業してまたプルリクを発行したい。という状況です。 > > この時に何も考えずに普通に作業を続行してプルリクを発行した場合、revertされた分の変更が失われてしまいます。 > > 結構でかい事故に繋がる場合があるので、この時の対処方法を書きたいと思います。 > > >
回答: これは revert という操作自体に問題があるというよりかは、revert が何をしているかの理解に問題があるのではないかと思います。私個人としては revert 自体に問題があるとは思いません(もちろんチームとして合意を取った上で revert は避けるという決定を否定するものではありません)。 まず大前提として、git revert は既に積んだコミットを打ち消すようなコミットを**新しく**積むコマンドです。既に積んだコミットを削除する、歴史改竄を伴うコマンドではありません。 ですから、revert したいコミットの後に、そのコミットで変更した部分を更に変更するコミットが積まれていれば、当然 revert 時点で conflict が発生します。 また、あるブランチ A をマージ、その後ブランチ A を revert した後にブランチ A を再度マージしようとすれば、ブランチ A の分岐点は revert した地点より前で既にマージされているコミットたちばかりなので、何も変わりません。revert で消えた変更を取り戻すには、たとえば revert の revert をすることで新しいコミットを積めば良いです。 以下、小さい動作例を示します。 ``` $ git init Initialized empty Git repository in /home/nek/tmp/rev/.git/ $ # 新しく example.txt を作成してコミットします。 $ echo foo > example.txt $ git add example.txt $ git commit -m "add example.txt" [master (root-commit) d0de588] add example.txt 1 file changed, 1 insertion(+) create mode 100644 example.txt $ # 先ほどコミットした example.txt を revert します。 $ git revert HEAD hint: Waiting for your editor to close the file... [master e93d91b] Revert "add example.txt" 1 file changed, 1 deletion(-) delete mode 100644 example.txt $ git log commit e93d91b3617f4d70f04ae8ed100f17d492350c32 (HEAD -> master) Author: nekketsuuu Date: Wed Aug 5 19:20:21 2020 +0900 Revert "add example.txt" This reverts commit d0de58827a3c518f12c2885a8db97ed2aec5ab94. commit d0de58827a3c518f12c2885a8db97ed2aec5ab94 Author: nekketsuuu Date: Wed Aug 5 19:19:42 2020 +0900 add example.txt $ # ファイルが削除されています $ ls $ # もう一度やってみます。 $ echo foo > example.txt $ git add example.txt $ git commit -m "add example.txt, again" [master 9124376] add example.txt, again 1 file changed, 1 insertion(+) create mode 100644 example.txt $ # 今度は conflict するような変更を挟んでみましょう。 $ echo bar > example.txt $ git add example.txt $ git commit -m "improve example.txt" [master a9eb03c] improve example.txt 1 file changed, 1 insertion(+), 1 deletion(-) $ # example.txt を作成したコミットを revert しようとすると conflict します。 $ git revert HEAD~1 error: could not revert 9124376... add example.txt, again hint: after resolving the conflicts, mark the corrected paths hint: with 'git add ' or 'git rm ' hint: and commit the result with 'git commit' nek@G-GEAR-NEK:~/tmp/rev$ git status On branch master You are currently reverting commit 9124376. (fix conflicts and run "git revert --continue") (use "git revert --abort" to cancel the revert operation) Unmerged paths: (use "git reset HEAD ..." to unstage) (use "git add/rm ..." as appropriate to mark resolution) deleted by them: example.txt no changes added to commit (use "git add" and/or "git commit -a") $ ls example.txt $ # ここでは削除する方を選択してみます。 $ git rm example.txt example.txt: needs merge rm 'example.txt' $ git revert --continue [master a48ed94] Revert "add example.txt, again" 1 file changed, 1 deletion(-) delete mode 100644 example.txt $ git log commit a48ed94fd72ba3bd2c6886f173dee46f8de3974e (HEAD -> master) Author: nekketsuuu Date: Wed Aug 5 19:22:48 2020 +0900 Revert "add example.txt, again" This reverts commit 912437675711610a16f9690244223c047d4276dc. commit a9eb03c37c08f884eca636d62f5d7e209d83b51d Author: nekketsuuu Date: Wed Aug 5 19:21:48 2020 +0900 improve example.txt commit 912437675711610a16f9690244223c047d4276dc Author: nekketsuuu Date: Wed Aug 5 19:21:24 2020 +0900 add example.txt, again (省略) $ # 無事削除されました。 $ ls $ # 最後にお試しとして、revert コミットを revert してみます。 $ git revert HEAD [master 037b437] Revert "Revert "add example.txt, again"" 1 file changed, 1 insertion(+) create mode 100644 example.txt $ git log commit 037b4371b6afd63b3197ecbfc8f0f48bbe6c9490 (HEAD -> master) Author: nekketsuuu Date: Wed Aug 5 19:23:10 2020 +0900 Revert "Revert "add example.txt, again"" This reverts commit a48ed94fd72ba3bd2c6886f173dee46f8de3974e. commit a48ed94fd72ba3bd2c6886f173dee46f8de3974e Author: nekketsuuu Date: Wed Aug 5 19:22:48 2020 +0900 Revert "add example.txt, again" This reverts commit 912437675711610a16f9690244223c047d4276dc. commit a9eb03c37c08f884eca636d62f5d7e209d83b51d Author: nekketsuuu Date: Wed Aug 5 19:21:48 2020 +0900 improve example.txt commit 912437675711610a16f9690244223c047d4276dc Author: nekketsuuu Date: Wed Aug 5 19:21:24 2020 +0900 add example.txt, again (省略) $ # foo ではなくて bar が戻ってきます。 $ cat example.txt bar $ ```