Git Revert Merge Commit: 例付きガイド

アプリケーションを問題のあるコードを統合することで妥協することができます。これがメインブランチに未完成のワークを不注意で統合した場合や、自動テストを通過した致命的なバグを見落とす場合のどちらかです。

この記事では、git revertを使って安全にマージを undo するプロセスをガイドします。これにより、コミット履歴が保持され、プロジェクトの整合性が保たれます。

How git revert Works

git revertはGitのundoコマンドのバージョンと考えられます。しかし、git revertコマンドはコミットを削除したり、ブランチの前の状態にジャンプしたりしません。代わりに、特定のコミットからの変更を元に戻す新しいコミットを作成します。

コミットハッシュの<commit_hash>でコミットを元に戻すための構文は:

git revert <commit_hash>

コミットとそのハッシュIDを一緒にリストアップするには、git logコマンドを使用します。git logの出力は最も新しいコミットから最も古いコミットまでのリストを示します:

例えば、引数関数を実装するコミットを元に戻すには、以下のコマンドを使用します:

git revert 7ba24a3e62d4d37182428ccfaa070baa222b1151

git revertを使用することで、特定のコミットの変更を元に戻すことができ、コミット履歴には影響を与えません。

コードの`git revert`は魔法ではなく、コミット履歴によっては手動で解決しなければならない冲突を引き起こす可能性があります。

`git revert`の手動変更に対する利点

  • なぜ、手動で変更を元に戻すよりも`git revert`が便利なのでしょうか?冲突を手動で解決する必要があるなら、手動で変更を元に戻す方が簡単ではありませんか?その利点を見てみましょう:
  • 履歴の保持:`git revert`は特定のコミットの変更を元に戻す新しいコミットを作成し、コミット履歴全体を保持します。これにより、変更と取り消しの透明な履歴を維持するのを助けます。
  • アトミックな取り消し:取り消しがアトミックであり一貫していることを確保します。手動で変更を削除しコミットする場合、人為的なエラーのリスクがあります。
  • 冲突の認識:元のコミットに依存するインテグレーションや変更がある場合に、冲突を通じて通知されることを確保します。これは不便に思えるかもしれませんが、意図しない副作用を防ぐために重要です。

メタデータ:`git revert`によって作成された新しいコミットには、メタデータとコンテキストに基づいたコミットメッセージが含まれており、どのような内容が元に戻されたかを理解するのに役立ちます。`git revert`を使用しないと、このコンテキストが失われる可能性があります。

異なるシナリオでのマージの取り消し

git merge feature

この節では、マージを元に戻す方法を学びます。例として、`feature`ブランチを`main`ブランチにマージし、`main`ブランチからコマンドを実行すると仮定しています:ここで学んだことを適切なブランチ名に置き換えることで、他の任意の2つのブランチに応用できます。

メージャーブランチ上のマージを取消すが、関連するコミットがない

git mergeコマンドは必ず新しいコミットを作成するわけではありません。コミットはmainブランチがfeatureブランチから分岐した場合にのみ作成されます。したがって、git revertはコミットが必要ですので、この場合では使用できません。

mainブランチとfeatureブランチが分岐するのは、mainに新しいコミットが作成され、それがfeatureブランチの祖先でない場合です。言い換えると、featureが作成された後、mainに新しいコミットが作成された場合です。

ブランチが分岐していない場合、mainブランチでgit merge featureコマンドを実行すると、Gitはファストフォワードを使用してマージします。これはmainブランチのHEADfeatureブランチのHEADに移動することを意味します。

これはgit mergeの結果を見ることで確認できます:

このようなマージを取消すためには、mainブランチのHEADを元の位置に戻すだけで十分です。それには:

  1. 前のHEADgit reflogを使用して特定します。
  2. 前のHEADにリセットするには、git reset --hard <previous_head>を使用し、<previous_head>を前のHEADに置き換えます。

git reflogの出力はこのような感じになります:

「checkout: moving from feature to main」と表示されている行を見て、前のHEADを特定できます(ここではfeaturemainというブランチ名を使用しています)。

この場合、前のヘッドはfe59838です。メインブランチのHEADを戻し、マージを元に戻すには、以下のコマンドを使用します:

git reset --hard fe59838

マージしたコミットを戻す

mainブランチとfeatureブランチが分岐している場合、ブランチをマージすると新しいコミットが作成され、マージコミットと呼ばれます。

マージコミットは、1つのブランチから他のブランチに変更を適用します。この場合、featureの変更がmainブランチに適用されます。

mainブランチの変更を戻すには、マージコミットに対してgit revertを使用します。これにより、新しいコミットが作成され、マージでmainブランチに導入された変更を元に戻し、ブランチの状態をマージ前の状態に復元します。

まず、マージコミットのハッシュを特定する必要があります。これにはgit logコマンドを使用します:

マージコミットは2つの親を持っているため、git revertのシンタックスがやや異なります。-m 1オプションを使用して、mainブランチに対する変更を戻すことを指定する必要があります:

git revert -m 1 b8dab2c8611e324ed0d273133987415350e6d10d

コミットの戻し時の衝突解決

コミットを戻す際に、特にコミットがコードベースの後続変更と衝突する場合、衝突が発生することがあります。その場合:

  1. Gitは戻しを一時停止します:手動で衝突を解決する必要があります。Gitは衝突するファイルをマークし、介入を求めます:
  2. 衝突を解決します:衝突をマークした各ファイルを開き、Gitによる解決を行い、変更を保存します:
  3. 解決したファイルをステージングします:git add <file-path>
  4. 戻しを続けます: git revert --continue

結論

git revertを使用してマージコミットを取り消すことで、すべての変更と修正がコミット履歴内に記録されます。

また、git resetgit revertを適切なシナリオで使い分ける理解は、特に共同作業やローカルでの変更を考慮した際に、より良い決定を行うのに役立ちます。

このوضوعについて更多信息は以下のFAQセクションで読むことができます。Gitをさらに学びたい場合は、以下のリソースを推荐します:

Source:
https://www.datacamp.com/tutorial/git-revert-merge