この記事は、ニフティグループ Advent Calendar 2024 15日目の記事です。
こんにちは! ニフティでエンジニアをしている西根です!
普段はニフティポイントクラブの開発運用保守をしています。
皆さんはgit revertは普段使用していますか?
私は最近までほとんど使用したことがありませんでした。
この記事はマージした後にrevertしたけど、その後どうすれば良いか何もわからない!困った!という人向けに書いていきたいと思います。
背景
先日ステージング環境へデプロイしたところ不具合が見つかり、一度切り戻しを実施することになりました。
今までのリリースではほとんど切り戻しを実施することがなく、初めてGitHubのrevertを使用しました。
ステージング環境へ反映した内容に少し修正を加えるだけだったので、revertして切り戻し実施後に元々developブランチにマージしたfeatureブランチにそのまま変更を加えました。
が、再リリースでdevelopへのマージ時に見えないコンフリクトが発生し、どうしたら良いかわからなくなってしまったので、同じような人がいたら助けになれば幸いです。
そもそもrevertとは?
公式ドキュメントでは以下のように説明されています。
1 つ以上の既存のコミットがある場合、関連するパッチによって導入された変更を元に戻し、それを記録するいくつかの新しいコミットを記録します。これには、作業ツリーがクリーンであること (HEAD コミットからの変更がない) が必要です。
https://git-scm.com/docs/git-revert.html
つまり、一言で言うと既存のコミットを打ち消すコミットを作成するコマンドです。
自分がいるブランチの最新のコミット(HEAD)からコミットしていない変更がない場合に使用できます。
なぜ再度マージする時にハマってしまったのか
前提としてブランチの運用ルールは以下の通りです
- main:本番稼働しているコード。
- develop:ステージング環境で稼働しているコードで、本番反映時にmainにマージする。
- feature:developブランチから切っており、機能開発時に使用する。ステージング反映時にdevelopブランチにマージする。
切り戻しを実施する時にdevelopブランチにマージしたPRをGitHub上でrevertし、ローカルにリモート上のrevertを取り込まないままfeatureブランチで修正を行なってしまいました。
今回はここが問題で、修正後のfeatureブランチをdevelopブランチにマージする時に、Gitが以下の状態を解決しようとしますが、同じ箇所に変更を加えている場合にはどちらの状態を採用すべきかを自動で判断することができず、コンフリクトとして扱われます。
- featureブランチの変更(一度developブランチにマージされた変更とrevert後の修正)
- developブランチのrevertによる打ち消し
コードの内容自体は同じように見えるのですが、Gitとしては変更履歴が異なるため、コンフリクト判定されてしまいました。
結論
今回のようなケースを避けるためには以下の手順でrevert後の修正をするのが良さそうです。
- revertしたブランチをpullしてリモートとローカルの差分をなくす
1git pull origin { revertしたブランチ }
- revertしたブランチでrevertのマージコミットのコミットハッシュを調べる
1git log --graph
*
がついているものがコミット
以下の場合はコミットハッシュ3のコミットがrevertのマージコミットになる - revertしたブランチで再度revertする
1git revert -m 1 { コミットハッシュ }
-m
: mainlineのm。マージコミットは親コミットが2つあるのでどちらに戻すのかを指定してあげる必要がある。親コミットの番号は1, 2で指定でき、1はマージされた側・2はマージする側を表している
今回はマージされたdevelopブランチの方に戻したいので、1を指定する - そこから修正ブランチを切る
1git switch -c { 修正ブランチ }
- 修正ブランチで修正しリモートにpushする
123git add { ファイル }git commit -m "{ コミットメッセージ }"git push origin { 修正ブランチ }
- GitHubでターゲットブランチにマージする
まとめ
(当たり前といえば当たり前ですが)リモートとの差分があるままローカルで作業しないことは常に心に留めておきたいですね。
目には見えないコンフリクトには皆さんもお気をつけください😭