できない.dev

Git revert でコンフリクトが出て元に戻せない

git revert でコンフリクトが発生したら、衝突箇所を手動で解決して git add → git revert --continue で続行する。
途中で諦める場合は git revert --abort で revert 自体を取り消せる。
マージコミットを revert するときは -m で親番号の指定が必須。

#revert#conflict#undo#merge-commit

公開:

要約

git revert でコンフリクトが出るのは、revert したい変更と現在の HEAD の内容が同じ行で食い違っているため。
コンフリクトマーカーを手動で編集 → git addgit revert --continue の順で進めれば再開できる。
途中で諦めるなら git revert --abort
マージコミットを revert する場合は -m で親番号の指定が必須。

よくある原因

  1. revert 対象のコミットが触ったファイルを、その後の別コミットがさらに変更しており、Git が自動で打ち消し差分を当てられない。
  2. マージコミットには親が 2 つあるため、git revert <merge-commit> だけでは「どちらの親に戻すか」を Git が決められず fatal: commit ... is a merge but no -m option was given で失敗する。
  3. コンフリクト解決中に git commit だけ実行してしまい、REVERT_HEAD の状態が解除されないまま履歴が中途半端になる。
  4. 既に手動で部分的に元に戻したコード片を、もう一度 git revert でも消そうとして同じ行を二重に削ろうとする。

解決策

1. コンフリクトマーカーを解決して continue する

git status                       # Unmerged paths: の一覧を確認
# エディタで <<<<<<< ======= >>>>>>> を編集
git add path/to/file
git revert --continue            # revert のコミットメッセージを編集して確定

--continue の代わりに git commit を打っても進めるが、git revert --continue を使うとデフォルトメッセージ(Revert "...")が自動で入る。

2. マージコミットの revert は親番号を指定する

git revert -m 1 <merge-commit>

-m 1 は「1 番目の親(通常は main 側)を残し、もう一方の親が持ち込んだ差分を打ち消す」という意味。
詳しくは 公式ドキュメント-m parent-number を参照。

3. 途中で諦めて元に戻す

git revert --abort

revert を始める前の HEAD と作業ツリーに戻る。--quit だと revert 状態だけクリアして作業ツリーは残るので、用途で使い分ける。

4. 連続コミットをまとめて revert する

git revert --no-commit <old>..<new>
# 必要なら手動で調整したあと
git commit -m "Revert a..b range"

--no-commit で打ち消し差分だけステージしておくと、複数のコミットを 1 つの revert コミットにまとめられる。

この記事は役立ちましたか?