Git での変更の取り消し: Reset、Restore、Revert の解説
git restore、reset、revert を理解して、ファイルのステージ解除、ローカル編集の破棄、コミットの取り消し、共有履歴の書き換え回避を実現しましょう。
Git での変更の取り消し: Reset、Restore、Revert の解説
Git での変更の取り消しは、作業ツリー、ステージングエリア、コミット履歴のどのレイヤーを変更しているかを把握していれば安全です。一般的なコマンドは git restore、git reset、git revert で、それぞれ異なる問題を解決します。
大原則はシンプルです。ファイルには restore、ローカル履歴の変更には reset、他の人がすでに持っている可能性のあるコミットの取り消しには revert を使います。
基本概念の理解
以下の領域を正しく把握しましょう。
- 作業ツリー: 編集するファイル。
- ステージングエリア(インデックスとも呼ばれる): 次のコミットに選択された変更。
- コミット履歴: すでに記録されたコミット。
HEAD: ブランチが現在指しているコミット。
何かを取り消す前に git status を実行しましょう。変更がステージングされていないか、ステージングされているか、すでにコミットされているかを教えてくれます。
git restore: 作業ディレクトリとステージングエリアの変更を破棄する
git restore は、ブランチ履歴を移動せずに作業ツリーやステージングエリアのファイルを変更したいときに使います。
ファイルのステージ解除
誤ってファイルをステージングした場合は、--staged でステージングを解除します。
git restore --staged <file>
すべてのステージングを解除するには:
git restore --staged .
ファイルの編集内容は作業ツリーに残ります。次のコミットから削除されるだけです。
作業ディレクトリの変更を破棄する
1つのファイルのステージングされていない編集を破棄するには:
git restore <file>
これにより、作業ツリーのコピーがインデックスと一致します。ファイルがステージングされていない場合、通常は HEAD に戻ります。ローカルの編集を破棄するため、最初に git diff を確認しましょう。
ファイルのステージングされた変更とステージングされていない変更の両方を破棄し、HEAD から復元するには:
git restore --source=HEAD --staged --worktree <file>
特定のコミットからファイルを復元する
古いコミットから1つのファイルを復元することもできます。
git restore --source=<commit> -- path/to/file
これにより、作業ツリーのファイルが変更されます。古いバージョンを今後使用したい場合は、コミットしてください。
git reset: 履歴の書き換え
git reset は、現在のブランチポインタを移動したいときに使います。モードによって、ステージングエリアや作業ツリーも変更できます。
モードの理解 (--soft、--mixed、--hard)
3つの一般的なモードは次のとおりです。
git reset --soft HEAD^
HEAD を1つ前のコミットに移動し、取り消したコミットの変更をステージングしたままにします。
git reset --mixed HEAD^
HEAD を1つ前のコミットに移動し、取り消したコミットの変更をステージングされていない状態に保ちます。--mixed がデフォルトなので、git reset HEAD^ も同じ動作です。
git reset --hard HEAD^
HEAD を1つ前のコミットに移動し、対応する変更をステージングエリアと作業ツリーから破棄します。これは破壊的です。軽率に実行しないでください。
便利なリセットパターン:
git reset --soft HEAD^ # 最後のローカルコミットをやり直し、変更をステージングしたままにする
git reset HEAD^ # 最後のローカルコミットを取り消し、変更をステージングされていない状態にする
git reset # すべてのステージングされた変更をステージング解除する
git reset --hard origin/main # ローカルの変更を破棄し、origin/main に合わせる
古いコミットのリセット
ブランチを2つ前のコミットに戻し、変更を作業ツリーに保持するには:
git reset --mixed HEAD~2
ローカルコミット、またはチームが書き換えに同意したコミットのみをリセットしてください。コミットがすでに共有ブランチにある場合は、git revert を優先しましょう。
git revert: 変更を取り消す新しいコミットを作成する
git revert は、以前のコミットの逆を適用する新しいコミットを作成します。元のコミットを削除したり移動したりしないため、共有ブランチでも安全です。
1つのコミットを元に戻す:
git revert <commit-hash>
範囲を元に戻す:
git revert HEAD~3..HEAD
競合が発生した場合は、解決し、ファイルをステージングして続行します:
git add <fixed-files>
git revert --continue
マージコミットを元に戻すには、Git がどの親をメインラインとして扱うべきかを知る必要があるため、特別な注意が必要です:
git revert -m 1 <merge-commit>
これは、マージが何を導入したかを理解している場合にのみ実行してください。プロダクションブランチでは、マージの元に戻す前にレビューを依頼しましょう。
適切なコマンドの選択
以下のクイックガイドを使用してください:
- ファイルのステージング解除:
git restore --staged <file>。 - ファイルのステージングされていない編集を破棄:
git restore <file>。 - 最後のローカルコミットを取り消し、変更をステージングしたままにする:
git reset --soft HEAD^。 - 最後のローカルコミットを取り消し、変更をステージングされていない状態にする:
git reset HEAD^。 - ローカルの変更とコミットを破壊的に破棄:
git reset --hard <commit>。 - プッシュされたコミットを安全に取り消す:
git revert <commit-hash>。
実践的なポイント
何かを取り消す前に、git status を実行し、何を変更しているかを判断しましょう。ファイルレベルのクリーンアップには restore、ローカルのプッシュされていないコミットには reset、共有履歴には revert を使用します。--hard を含むコマンドの場合は、一時停止して最初に git diff を確認しましょう。