git resetとは?コミット取り消しを安全に行う3つのモードを解説

「さっきのコミット、取り消したい…」そんな経験はありませんか。コミットメッセージを間違えた、余計なファイルを含めてしまった、そもそも変更内容を見直したい。Gitで開発していると、こうした「やり直し」が必要になる場面は意外と多いものです。

そんなときに活躍するのがgit resetコマンドです。このコマンドを使いこなせば、コミットの取り消しからステージングの解除まで、さまざまな「取り消し」操作を柔軟に行えます。この記事では、git resetの3つのモード(--soft--mixed--hard)の違いと、安全に使うためのベストプラクティスを解説します。

目次

git resetの概要

git resetは、現在のHEAD(ブランチの先端)を指定した状態にリセットするGitコマンドです。コミット履歴の操作、ステージングの取り消し、作業ディレクトリの復元など、バージョン管理における「取り消し」操作の中核を担います。

このコマンドが強力なのは、影響範囲を細かく制御できる点にあります。--soft--mixed--hardという3つのモードを使い分けることで、「コミットだけ取り消したい」「ステージングも解除したい」「変更自体をなかったことにしたい」といった異なるニーズに対応できます。

Stack Overflowでは「how to undo the most recent commit(直前のコミットを取り消すには)」という質問が7百万回以上閲覧され、1万を超える投票を集めています。それだけ多くの開発者がコミットの取り消しに悩み、git resetを必要としているということです。

3つのモードの違いを理解する

git resetを使いこなすには、Gitの「3つのツリー」を理解することが重要です。Gitは内部的に、HEAD(コミット履歴)、インデックス(ステージングエリア)、作業ディレクトリという3つの領域でファイルを管理しています。各モードはこれらのどこまでをリセットするかが異なります。

項目–soft–mixed(デフォルト)–hard
HEAD移動する移動する移動する
インデックス変更しないリセットするリセットする
作業ディレクトリ変更しない変更しないリセットする
変更の保持すべて保持すべて保持(未ステージ状態)すべて破棄

–soft:コミットだけを取り消す

--softはHEADの位置だけを移動させ、インデックスと作業ディレクトリには一切触れません。つまり、コミットは取り消されますが、変更内容はステージング済みの状態で残ります。

# 直前のコミットを取り消す(変更はステージング済みのまま)
git reset --soft HEAD~1

このモードは「コミットをやり直したい」ときに最適です。たとえば、コミットメッセージを修正したい場合や、別のファイルも一緒にコミットしたかった場合に使います。リセット後、すぐにgit commitを実行すれば新しいコミットを作成できます。

–mixed:ステージングも解除する

--mixedはデフォルトのモードで、HEADとインデックスをリセットしますが、作業ディレクトリは維持します。変更内容は残りますが、ステージングされていない状態になります。

# 直前のコミットを取り消す(変更は作業ディレクトリに残る)
git reset HEAD~1

# または明示的に指定
git reset --mixed HEAD~1

git addを取り消したい」「ステージングした変更を再編集したい」といった場面で活用できます。変更自体は失われないので、安心して使用できるモードです。

–hard:すべてをリセットする

--hardはHEAD、インデックス、作業ディレクトリのすべてをリセットします。指定したコミットの状態に完全に戻るため、それ以降のすべての変更が破棄されます。

# 直前のコミットを取り消す(変更も完全に破棄)
git reset --hard HEAD~1

# 特定のコミットまで戻る
git reset --hard abc1234

実験的なコードを完全に破棄したい場合や、クリーンな状態に戻したい場合に使用します。ただし、コミットしていない変更は復元できなくなるため、慎重に操作する必要があります。

基本的な使い方

ここからは、よく使うgit resetのパターンを紹介します。

ファイルをステージングから外す

特定のファイルだけをステージングから外したい場合は、ファイルパスを指定します。

# 特定のファイルをステージングから外す
git reset -- src/config.js

# 複数ファイルを指定
git reset -- src/config.js src/utils.js

なお、Git 2.23以降ではgit restore --stagedコマンドが推奨されています。より直感的な名前で同じ操作ができます。

# git restore を使う場合(Git 2.23以降)
git restore --staged src/config.js

直前のコミットを修正する

コミットメッセージを間違えた、ファイルを追加し忘れた、といった場合の対処法です。

# 直前のコミットを取り消し(変更はステージング済み)
git reset --soft HEAD~1

# 必要な修正を行う
# ...

# 新しいコミットを作成
git commit -m "正しいコミットメッセージ"

ちなみに、単純なコミットメッセージの修正だけならgit commit --amendの方が手軽です。

複数のコミットをまとめる

作業中に細かくコミットしすぎた場合、それらをまとめたいことがあります。

# 直近3つのコミットを取り消す
git reset --soft HEAD~3

# まとめて1つのコミットにする
git commit -m "機能Xの実装"

マージを取り消す

マージ後に問題が発覚した場合、ORIG_HEADを使ってマージ前の状態に戻せます。Gitはresetやmergeなどの操作前に、元のHEADの位置をORIG_HEADとして保存してくれます。

# マージを実行
git merge feature-branch

# 問題発覚、マージ前に戻す
git reset --hard ORIG_HEAD

git reset と git revert の使い分け

「コミットを取り消す」という目的ではgit revertも選択肢になります。両者の違いを理解しておくことが重要です。

git resetはコミット履歴を書き換えます。指定したコミット以降の履歴が消えるため、ローカルでの作業には便利ですが、すでにリモートにプッシュしたコミットに対して使うと問題が発生します。

# resetは履歴を書き換える
# A - B - C (HEAD)
git reset --hard HEAD~1
# A - B (HEAD)  ← Cは履歴から消える

一方、git revertは指定したコミットを打ち消す新しいコミットを作成します。履歴は保持されるため、共有ブランチでも安全に使用できます。

# revertは打ち消しコミットを作成
# A - B - C (HEAD)
git revert HEAD
# A - B - C - C' (HEAD)  ← C'はCを打ち消すコミット

チームで作業している場合、プッシュ済みのコミットを取り消すにはgit revertを使いましょう。git resetはローカルの未公開コミットに対してのみ使用するのが基本です。

ベストプラクティス

git resetを安全に使うためのポイントをまとめます。

ローカル作業でのみ使用する

git resetは履歴を書き換えるコマンドです。すでにリモートにプッシュしたコミットに対して使用すると、他の開発者がプルした後に履歴が不整合になり、コンフリクトや混乱の原因となります。共有ブランチではgit revertを使用してください。

段階的にリセットする

いきなり--hardを使うのではなく、まずは--softで様子を見ることをおすすめします。--softで問題なければ--mixed、それでも変更を破棄したい場合のみ--hardという順序で試すことで、意図しないデータ損失を防げます。

reflogを知っておく

--hardで誤って変更を消してしまった場合でも、コミット済みであればgit reflogから復元できる可能性があります。reflogはHEADの移動履歴を記録しており、過去の状態に戻るための命綱となります。

# reflogで履歴を確認
git reflog

# 出力例
# abc1234 HEAD@{0}: reset: moving to HEAD~1
# def5678 HEAD@{1}: commit: 重要な変更
# ...

# 特定の状態に戻す
git reset --hard HEAD@{1}

ただし、コミットしていない変更は復元できません。重要な変更は早めにコミットするか、git stashで一時保存しておきましょう。

よくある質問

–hardで消した変更を復元できますか?

コミット済みの変更であればgit reflogから復元できる可能性があります。ただし、コミットしていなかった変更は復元できません。重要な作業中は定期的にコミットすることをおすすめします。

HEAD~1とHEAD^の違いは何ですか?

どちらも「直前のコミット」を指します。HEAD~nはn個前のコミット、HEAD^は直前のコミットを意味します。HEAD~1HEAD^は同じ結果になりますが、マージコミットの場合は挙動が異なることがあります。

プッシュ済みのコミットをresetしてしまいました。どうすればいいですか?

2つの選択肢があります。1つ目はgit push --forceでリモートを上書きする方法ですが、チームメンバーに影響を与えるため注意が必要です。2つ目はgit pullでリモートの状態を取り込み、git revertで対処する方法です。チーム開発では後者が安全です。

まとめ

git resetは、Gitでの「取り消し」操作の中核を担う強力なコマンドです。3つのモードの違いを理解しておくことで、状況に応じた適切な取り消し操作ができるようになります。

--softはコミットのやり直しに、--mixedはステージングの解除に、--hardは完全なリセットに使用します。ただし、--hardは変更を完全に破棄するため、段階的に試すことをおすすめします。

また、プッシュ済みのコミットに対してはgit resetではなくgit revertを使用することで、チームでの混乱を避けられます。reflogという復元手段があることも覚えておくと、いざというときに役立ちます。

参考リンク

Git公式ドキュメント – git-reset:すべてのオプションと動作が網羅された公式リファレンスです。

Pro Git Book – Reset Demystified:git resetの内部動作を3つのツリーの観点から詳しく解説しています。

Atlassian Git Tutorial – git reset:図解を交えた分かりやすい解説で、reset・checkout・revertの違いも説明されています。

さらに深く学びたい方へ

この記事で紹介した技術をマスターするには、体系的な学習が重要です。独学で挫折しそうな方は、現役
エンジニアから直接学べるプログラミングスクールも検討してみてください。

現場で通用するスキルを身につけるなら

DMM WEBCAMPのカリキュラムは、実際の開発現場を想定したチーム開発も経験できます。ポートフォリオ制作
支援もあり、転職活動で差をつけられます。

未経験から4ヶ月でエンジニアとして活躍できるレベルまで成長可能です。

実務レベルのWeb開発スキルを習得するなら

RUNTEQは、1000時間の圧倒的学習量で、現場で即戦力となるWebエンジニアを育成します。Ruby on
Railsに特化し、実際のWebサービス開発を通じて実践力を養います。

卒業生の多くが自社開発企業への転職に成功している実績があります。

じっくり理解を深めたい方へ

この記事で紹介した内容を確実に身につけるには、分からない点をすぐに質問できる環境が重要です。CodeCa
mpなら、現役エンジニアとのマンツーマンレッスンで、あなたのペースで着実にスキルアップできます。

朝7時〜夜23時まで、365日受講可能なので、仕事や学業と両立しながら学習を進められます。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次