アプリケーションを問題のあるコードを統合することで妥協することができます。これがメインブランチに未完成のワークを不注意で統合した場合や、自動テストを通過した致命的なバグを見落とす場合のどちらかです。
この記事では、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
ブランチのHEAD
をfeature
ブランチのHEAD
に移動することを意味します。
これはgit merge
の結果を見ることで確認できます:
このようなマージを取消すためには、main
ブランチのHEAD
を元の位置に戻すだけで十分です。それには:
- 前の
HEAD
をgit reflog
を使用して特定します。 - 前の
HEAD
にリセットするには、git reset --hard <previous_head>
を使用し、<previous_head>
を前のHEAD
に置き換えます。
git reflog
の出力はこのような感じになります:
「checkout: moving from feature to main」と表示されている行を見て、前のHEAD
を特定できます(ここではfeature
とmain
というブランチ名を使用しています)。
この場合、前のヘッドは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
コミットの戻し時の衝突解決
コミットを戻す際に、特にコミットがコードベースの後続変更と衝突する場合、衝突が発生することがあります。その場合:
- Gitは戻しを一時停止します:手動で衝突を解決する必要があります。Gitは衝突するファイルをマークし、介入を求めます:
- 衝突を解決します:衝突をマークした各ファイルを開き、Gitによる解決を行い、変更を保存します:
- 解決したファイルをステージングします:
git add <file-path>
- 戻しを続けます:
git revert --continue
結論
git revert
を使用してマージコミットを取り消すことで、すべての変更と修正がコミット履歴内に記録されます。
また、git reset
とgit revert
を適切なシナリオで使い分ける理解は、特に共同作業やローカルでの変更を考慮した際に、より良い決定を行うのに役立ちます。
このوضوعについて更多信息は以下のFAQセクションで読むことができます。Gitをさらに学びたい場合は、以下のリソースを推荐します: