Git: コミットを取り消す
最終更新
コミットの取り消し方は、どのコミットかと、それをすでにプッシュしたかどうかで決まります。履歴の途中に埋もれた過去のコミットや、すでに共有されたものには git revert を使います。何も書き換えずに、そのコミットを打ち消す新しいコミットを追加するからです。直近のローカルコミットの連なりなら、git reset で単純に巻き戻せます。直前のコミットだけを取り消したいなら、直前のコミットの取り消しページがその手早い修正のあらゆるパターンを扱っています。
これらをターミナルプレイグラウンドで試してみましょう。ブラウザ上の本物のシェルで、インストールは不要です。
どのコマンドを使うか
| Situation | Command |
|---|---|
| 過去のコミットを 1 つ取り消し、その後のコミットはすべて残す | git revert <hash> |
| すでにプッシュしたコミットを取り消す | git revert <hash> |
| 直近のローカルコミット 3 つを取り消し、作業内容は残す | git reset --soft HEAD~3 |
| 直近のローカルコミット 3 つを取り消し、作業内容も破棄する | git reset --hard HEAD~3 |
| 範囲を新しい打ち消しコミットで取り消す | git revert HEAD~3..HEAD |
reset vs revert
| Behavior | git reset | git revert |
|---|---|---|
| 履歴を書き換える | はい | いいえ |
| プッシュ済みコミットで安全 | いいえ | はい |
| 新しいコミットを作成する | いいえ | はい |
| 履歴の途中の古いコミットに使える | いいえ | はい |
| 変更を破棄できる | はい (--hard) | いいえ |
実践例
後続のコミットに一切触れずに、特定の過去のコミット(プッシュ済みでも)を取り消す。
| Step | Command | Result |
|---|---|---|
| 1 | git log --oneline | 問題のコミットのハッシュを見つける(例: a1b2c3d) |
| 2 | git revert a1b2c3d | 新しいコミットがそれを打ち消し、後続のコミットは無傷のまま |
| 3 | git push | 修正を共有する - 履歴は一切書き換えられていない |
Git コミット取り消しに関するよくある質問
その後のコミットを失わずに過去のコミットを取り消すには?
git revert <hash> を使います。revert は指定したコミットだけを打ち消す新しいコミットを作成し、それ以降のコミットはすべて元のまま残ります。まず git log --oneline でハッシュを見つけてください。revert が後の変更と競合した場合、Git は一時停止するので、解決してから git revert --continue を実行します。複数のコミットを一度に取り消すには?
ローカルのみのコミットなら、
git reset --soft HEAD~3 が直近の 3 つを取り除きつつ、その変更をステージしたまま残します(破棄するには --hard)。プッシュ済みのコミットは代わりに範囲を revert します。git revert --no-commit HEAD~3..HEAD が 3 つすべてを打ち消し、最後の 1 回の git commit が取り消しを記録します。すでにプッシュしたコミットを取り消すには?
reset の代わりに
git revert <hash> を使います。revert は対象コミットの変更を打ち消す新しいコミットを作成し、履歴はそのまま残します。これが共有されたコミットを取り消す安全な方法です。reset でプッシュ済み履歴を書き換えると、他の全員が自分のコピーを整合させる必要が生じます。reset と revert はどう使い分けますか?
コミットが自分だけのもので、まだローカルにあるなら reset です。何もなかったかのように、ブランチを単に元へ戻します。コミットがプッシュ済み・共有済み、または履歴の途中にあるなら revert です。全員が安全に pull できる新しいコミットで変更を取り消します。
これをオンラインで練習できますか?
はい。ターミナルプレイグラウンドを開けば、ブラウザ上の本物のシェルでこれらのコマンドを実行できます。インストールは不要です。Coddy の無料インタラクティブ Git コースでも、変更の取り消しを段階的に扱っています。