git resetの使い方とsoft / mixed / hardの違い|コミット取り消しから復元まで解説

コマンドリファレンス

Gitでコミットした後に「やり直したい」と思う場面は頻繁にあります。コミットメッセージを書き間違えたり、余計なファイルをコミットしてしまったり、作業途中でコミットしてしまったりと、理由は様々です。

本記事では、Gitでコミットやステージング(add)を取り消すための強力なコマンド「git reset」の使い方を、図解を交えて分かりやすく解説します。

初心者にとって混乱しやすい「–soft」「–mixed」「–hard」のオプションの違いから、万が一間違えてリセットしてしまった場合の復旧手順(git reflog)、さらには git revertgit restore との違いまで網羅しています。この記事を読めば、Gitでの「巻き戻し」操作に迷いがなくなり、安全に作業をやり直せるようになります。

  1. git resetでよく使うコマンド早見表
  2. 1. git resetの基本概念と3つのオプションの違い
    1. 1-1. git resetとは?
    2. 1-2. soft / mixed / hard オプションの影響範囲(図解)
    3. 1-3. –soft:コミットのみを取り消す(直前の修正向け)
    4. 1-4. –mixed:コミットとステージングを取り消す(デフォルト)
    5. 1-5. –hard:すべての変更を完全に破棄して戻す(取り扱い注意)
  3. 2. 【シーン別】git resetの具体的な使い方・ユースケース
    1. 2-1. 直前のコミットを取り消したいとき
    2. 2-2. 複数(N個前)のコミットをまとめて1つにしたいとき
    3. 2-3. 特定の過去コミットの状態まで戻したいとき
    4. 2-4. git add(ステージング)だけを取り消したいとき
  4. 3. 直前コミットをその場で修正するなら「git commit –amend」
    1. 3-1. コミットメッセージだけを修正する
    2. 3-2. 追加し忘れたファイルを含めてコミットし直す
    3. 3-3. git reset –soft との使い分け
  5. 4. 【救済策】git reset –hardで消したコミットを「git reflog」で復元する手順
    1. 4-1. git reflogとは?
    2. 4-2. 誤操作から元の状態へ復元する3ステップ
    3. 4-3. 未コミットの変更は復元できない点に注意
  6. 5. 類似コマンドとの違いと使い分け(restore / revert)
    1. 5-1. git reset と git revert の違い(プッシュ済みの取り消し)
    2. 5-2. git reset と git restore(旧 checkout)の違い(ファイル変更の破棄)
  7. 6. git resetを使う際の重要ルールと事故防止策
    1. 6-1. ルール:プッシュ済みの共有ブランチでは絶対に使わない
    2. 6-2. 対策:実行前に git status と git diff で状態を確認する
    3. 6-3. 対策:迷ったら git stash で作業内容を退避しておく
  8. よくある質問(FAQ)
    1. HEAD^ と HEAD~1 に違いはありますか?
    2. reset --soft と --mixed はどちらを使うべきですか?
    3. amendした後にプッシュしたら拒否されたのですが?
    4. コミットを取り消した後にリモートの変更と同期するには?
  9. まとめ
  10. 関連記事

git resetでよく使うコマンド早見表

まず、コミットの取り消し・修正で最もよく使われるコマンドとオプションの早見表です。状況に合わせて使い分けましょう。

やりたいこと実行するコマンドオプション変更ファイルの扱い
直前のコミットメッセージを直したい / コミットをまとめたいgit reset --soft HEAD^--softステージングエリアに残る(git addされた状態)
コミットをなかったことにして、addからやり直したいgit reset --mixed HEAD^(または git reset HEAD^--mixed(デフォルト)ワーキングツリーに残る(add前の状態に戻る)
ミスしたコミットとその変更をすべて消去したいgit reset --hard HEAD^--hard完全に削除される(復元が困難なので注意)
直前のコミットメッセージだけを変更したいgit commit --amend -m "新しいメッセージ"直前のコミットが上書きされる

1. git resetの基本概念と3つのオプションの違い

1-1. git resetとは?

git reset は、リポジトリの「HEADの位置(コミット履歴のポインタ)」を指定したコミットまで移動(巻き戻し)させるコマンドです。Gitは、「コミット履歴(HEAD)」「ステージングエリア(Index)」「作業ディレクトリ(Working Tree)」の3つのツリーでファイルを管理しています。

git reset に指定するオプションによって、巻き戻した際に「Index」と「Working Tree」の状態をどう処理するかが異なります。

1-2. soft / mixed / hard オプションの影響範囲(図解)

各オプションが3つのエリアにどのように影響するかを図解で示します。

+-------------------------------------------------------------+
|                     [ git reset オプション比較 ]             |
|                                                             |
|           HEAD (コミット履歴)    Index (ステージ)   Working Tree (ファイル) |
|                  |                   |                   |          |
|                  v                   v                   v          |
|  --soft  :    巻き戻る            変更残る            変更残る       |
|                                (ステージ済)                         |
|                                                                     |
|  --mixed :    巻き戻る            巻き戻る            変更残る       |
|              (デフォルト)        (ステージ解除)      (ファイル残る)  |
|                                                                     |
|  --hard  :    巻き戻る            巻き戻る            巻き戻る       |
|                                                      (全て消去)     |
+-------------------------------------------------------------+

1-3. –soft:コミットのみを取り消す(直前の修正向け)

--soft オプションは、コミット履歴(HEAD)のみを過去に戻し、ファイル変更や git add した状態(ステージングエリア)はそのまま維持します。

# 直前のコミットを取り消して、ステージング状態に戻す
git reset --soft HEAD^

こんな時におすすめ:
「コミットした直後に、コミットメッセージの間違いに気づいた」「複数のコミットを1つにまとめてからプッシュしたい(ローカルの履歴整理)」といったケースに最適です。実行後、そのまま git commit を行えば、メッセージを修正してコミットし直せます。

1-4. –mixed:コミットとステージングを取り消す(デフォルト)

--mixed オプションは、コミット履歴(HEAD)とステージングエリア(Index)の両方を過去に戻します。ファイルの変更内容自体は作業ディレクトリ(Working Tree)にそのまま残ります。オプションを省略した場合は、自動的に --mixed が適用されます。

# コミットとステージングを取り消す(--mixed は省略可能)
git reset HEAD^

こんな時におすすめ:
「コミットしたけれど、構成やファイルを再度選び直して git add からやり直したい」という場合に便利です。ファイル自体は消えないため、安全にやり直しができます。

1-5. –hard:すべての変更を完全に破棄して戻す(取り扱い注意)

--hard オプションは、コミット履歴(HEAD)、ステージングエリア(Index)、そして作業ディレクトリ(Working Tree)のすべての変更を、指定したコミットの状態に強制的に巻き戻します。

# 直前のコミットとその変更を完全に消去する
git reset --hard HEAD^

注意点:
このコマンドを実行すると、前回のコミット以降に書いたソースコードは完全に削除され、復元できなくなります。まだコミットしていない作業中の変更も失われます。実行する前には、必ず git statusgit diff で未保存の重要な作業がないか確認してください。

2. 【シーン別】git resetの具体的な使い方・ユースケース

2-1. 直前のコミットを取り消したいとき

直前のコミットを取り消すには、戻り先として HEAD^ または HEAD~1 を指定します。

# 例: ファイルの変更を残したままコミットだけ取り消す
git reset --soft HEAD^

HEAD^ は「現在のHEAD(最新コミット)の1つ前の親コミット」を意味します。

2-2. 複数(N個前)のコミットをまとめて1つにしたいとき

ローカルで細かくコミットを刻みすぎた場合、プッシュする前にそれらを1つのきれいなコミットにまとめることができます。例えば、直近の3つのコミットをまとめたい場合は、3つ前(HEAD~3)に --soft でリセットします。

# 3つ前まで履歴を戻し、変更内容はステージングに残す
git reset --soft HEAD~3

# 新しいメッセージでまとめてコミット
git commit -m "機能実装(3つのコミットを集約)"

2-3. 特定の過去コミットの状態まで戻したいとき

ログから取得した具体的なコミットID(ハッシュ値)を指定することで、そのコミット時点まで一気に巻き戻すことができます。

# コミット履歴を確認
git log --oneline
# 出力例: 
# a1b2c3d (HEAD -> main) 最新コミット
# e4f5g6h 2つ前のコミット
# 7i8j9k0 戻したい過去のコミット

# 指定したコミット(7i8j9k0)の状態まで強制的に戻す
git reset --hard 7i8j9k0

2-4. git add(ステージング)だけを取り消したいとき

間違えて git add してしまったファイルをステージングエリアから除外したい(コミット対象から外したい)場合、コミット自体は戻さず、特定のファイルだけをリセットできます。

# すべてのステージングを取り消す
git reset

# 特定のファイルだけステージングを取り消す
git reset file_name.txt

※なお、現代のGit(バージョン2.23以降)では、ステージングの解除には git restore --staged <file> の使用が推奨されていますが、git reset も同様に機能します。

3. 直前コミットをその場で修正するなら「git commit –amend」

直前のコミットをやり直す場合、一度 git reset をしてからコミットし直すよりも、「git commit –amend」を使うほうが素早く安全に対応できます。このコマンドは、新しいコミット履歴を作るのではなく、直前のコミット自体を書き換えます。

3-1. コミットメッセージだけを修正する

ファイルの変更はそのままで、メッセージの間違いだけを直したい場合のコマンドです。

# コミットメッセージを変更して直前コミットを上書き
git commit --amend -m "正しいコミットメッセージ"

3-2. 追加し忘れたファイルを含めてコミットし直す

「一部のファイルの修正を入れ忘れたままコミットしてしまった」という場合は、忘れていたファイルを add してから --amend を実行します。

# 追加し忘れたファイルをステージング
git add forgotten_file.js

# コミットメッセージはそのままで、直前のコミットに統合
git commit --amend --no-edit

--no-edit を付与すると、コミットメッセージ編集用のエディタを起動せずに、元のメッセージのままでコミットを上書きできます。

3-3. git reset –soft との使い分け

直前コミットの修正は git reset --softgit commit --amend のどちらでも可能ですが、目的によって使い分けると作業効率が向上します。

状況・目的推奨するアプローチ理由
直前のコミットメッセージや構成をサクッと直したいgit commit --amend1コマンドで直接書き換えるため手軽で速い
直前だけでなく、数個前のコミットも巻き込んで履歴を再整理したいgit reset --soft HEAD~N複数コミットの変更を1箇所に集約して再コミットできる
どのファイルをコミットに含めるか、ステージングから吟味し直したいgit reset HEAD^ (mixed)コミットとステージングの両方を解除して冷静に再確認できる

4. 【救済策】git reset –hardで消したコミットを「git reflog」で復元する手順

「誤って git reset --hard を実行してしまい、大切なコミットが消えてしまった!」という場合でも、諦める必要はありません。ローカルの作業履歴である「git reflog」を使えば、削除されたコミットを復元できます。

4-1. git reflogとは?

git reflog は、コミットだけでなく resetcheckoutmerge など、ローカルで行った「HEADの移動操作」をすべて時系列で記録しているコマンドです。通常の git log には表示されない「削除されたはずのコミット」も、この履歴に残っています。

4-2. 誤操作から元の状態へ復元する3ステップ

誤操作をしてしまった場合、以下のステップで復元を行ってください。

ステップ 1: 操作履歴を表示する
まず、以下のコマンドを実行します。

git reflog

出力結果例:

a1b2c3d HEAD@{0}: reset: moving to HEAD^  <-- 間違えてresetした操作
e4f5g6h HEAD@{1}: commit: 実装完了(戻したいコミット!)
7i8j9k0 HEAD@{2}: checkout: moving from develop to feature-A

ステップ 2: 戻したいポイント(コミットIDまたはHEAD@{n})を特定する
出力された履歴の上から順に見ていき、間違えて reset する直前のコミットを探します。上記の例では、HEAD@{1}(コミットID: e4f5g6h)が戻したい状態です。

ステップ 3: 強制リセットで復元を実行する
特定したコミットIDまたは HEAD@{n} を指定して、--hard でリセットを行います。

# コミットIDで指定して復元する場合
git reset --hard e4f5g6h

# HEAD@{n}のインデックスで指定して復元する場合
git reset --hard HEAD@{1}

これで、削除されたコミットとワーキングツリーのファイルが、無事誤操作前の状態に復元されます。

4-3. 未コミットの変更は復元できない点に注意

git reflog はあくまで「コミット(あるいはHEADの移動)された履歴」をたどるものです。そのため、一度も git commit していない(または一度も git add して記録に残っていない)ファイルの変更内容は、git reset --hard で消してしまうと reflog でも復元できません。リセット前の確認が極めて重要とされるのはこのためです。

5. 類似コマンドとの違いと使い分け(restore / revert)

Gitには reset 以外にも「状態を戻す」ためのコマンドが存在します。これらを正しく使い分けることで、より安全に開発を行うことができます。

5-1. git reset と git revert の違い(プッシュ済みの取り消し)

git revert は、過去のコミット履歴を削除するのではなく、「指定したコミットの変更内容を打ち消すための新たなコミット」を作成するコマンドです。

# 指定したコミットの変更内容を打ち消す新しいコミットを作成
git revert a1b2c3d

使い分け:
すでにリモートリポジトリに push してチームメンバーと共有してしまったコミットは、git reset で履歴から消し去ると他の人のリポジトリと競合が発生し、大混乱を招きます。「プッシュ前なら git reset」「プッシュ後なら git revert」と覚えましょう。

5-2. git reset と git restore(旧 checkout)の違い(ファイル変更の破棄)

git restore は、特定のファイルの変更を取り消したり、ステージングを解除したりするためのコマンドです(Git 2.23で導入され、かつて git checkout が担っていたファイル操作機能を切り離したものです)。

# ファイルの編集内容を破棄して、前回のコミット時点に戻す(ワークツリーの復元)
git restore src/index.js

# 特定のファイルをステージングから除外する(ステージの復元)
git restore --staged src/index.js

使い分け:
git reset は「コミット履歴の位置」そのものを戻すコマンドであるのに対し、git restore は「ファイルの編集内容を無かったことにする(ファイルを元の状態に戻す)」ためのコマンドです。履歴をいじる必要がなく、ただファイル単体を戻したいときは git restore を使用します。

6. git resetを使う際の重要ルールと事故防止策

6-1. ルール:プッシュ済みの共有ブランチでは絶対に使わない

git reset は「ローカル専用 of タイムマシン」です。すでにGitHubなどのリモートに送信し、他の開発者がその上にコードを書いている可能性がある共有ブランチ(main, develop など)では、決して使用してはいけません。どうしても取り消す必要がある場合は、前述の git revert を使用してください。

6-2. 対策:実行前に git status と git diff で状態を確認する

特に --hard オプションを使う前には、失われるファイルが無いかを確実に確認してください。ワンクッション置いて確認する習慣をつけるだけで、不要なデータ紛失事故は防げます。

# 現在ステージされているファイル、変更されたファイルの一覧を確認
git status

# 具体的にどのコードが書き換わっているか差分を確認
git diff

6-3. 対策:迷ったら git stash で作業内容を退避しておく

「このコミットは取り消したいが、今書いている書きかけのコードが消えるのは困る」「削除するかどうか迷っている」という場合は、git stash を使って変更内容を一時避難(退避)させてから reset を行いましょう。

# 1. 現在の変更を一時退避
git stash

# 2. resetを実行して履歴を整える
git reset --hard HEAD^

# 3. 退避していた変更をワーキングツリーに戻す
git stash pop

よくある質問(FAQ)

HEAD^ と HEAD~1 に違いはありますか?

基本的に「1つ前のコミット」を指す上では全く同じ意味です。ただし、複数遡る際の表記ルールが異なります。HEAD^^(キャレットを2つ)と HEAD~2(チルダと数値)はともに「2つ前のコミット」を指しますが、さらに多く遡る場合は HEAD~5 のように数値を指定できるチルダ(~)表記の方が便利です。

reset --soft と --mixed はどちらを使うべきですか?

迷ったら --mixed(オプションなしのデフォルト)が安全です。なぜならファイル変更が残るため、データが消える心配がないからです。コミットメッセージの修正だけであれば --soft の方が git add の手間が省けるためスムーズです。

amendした後にプッシュしたら拒否されたのですが?

git commit --amend はローカルのコミット履歴を書き換えます。そのため、すでにリモートにプッシュ済みのコミットに対して amend を行うと、リモートと履歴の不整合が起きるためプッシュが拒否されます。自分だけの作業ブランチであれば git push --force-with-lease で強制上書きできますが、チームで使うブランチでは行わないようにしてください。

コミットを取り消した後にリモートの変更と同期するには?

ローカルで git reset して過去に戻った後、リモートの最新状態を取り込むには git pull --rebase を使うのが推奨されます。単に git pull を行うと、取り消したはずのコミットがマージコミットとして復活してしまいます。

まとめ

git reset は、Gitの基本操作の中でも非常に強力で、使いこなせば開発効率を飛躍的に向上させられます。一方で、履歴を書き換えるため扱いには十分な注意が必要です。

  1. --soft: コミットだけ取り消し。変更はステージングに残る(最速の再コミット向き)。
  2. --mixed(デフォルト): コミットとステージングを取り消し。変更はファイルに残る(addの再選択向き)。
  3. --hard: すべて消去。未コミットの変更は失われるため、実行前に必ず状態確認を。
  4. プッシュ後は revert: 共有ブランチの変更は、履歴を書き換えない git revert を使用する。
  5. 誤操作は reflog: git reset --hard で誤って消してしまった場合でも、git reflog から復元可能。
Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント