【Git】コミットの取り消し方|reset・revert・amendの使い分け完全ガイド

【Git】コミットの取り消し方 Git

Gitで作業していると「さっきのコミット、やっぱりやり直したい」という場面に必ず遭遇します。コードを間違えて含めてしまった、コミットメッセージを打ち間違えた、公開しないファイルを入れてしまった、そもそも不要なコミットだった——原因はさまざまですが、焦ってgit reset --hardを叩くとかえって手元の作業を失うことがあります。

この記事では、Gitのコミットを取り消す方法を状況別に体系的にまとめ、「まだpushしていない/push済み」「変更は残したい/破棄したい」「メッセージだけ直したい」といったケースに対し、正しいコマンドと落とし穴、そして失敗したときのリカバリ方法までを解説します。Git公式ドキュメントと現場での実践パターンに沿って、安全に履歴を戻すための判断基準を手に入れましょう。

この記事で学べること

  • コミット取り消しの前に確認すべきこと(push済みか・共有ブランチか)
  • git reset--soft / --mixed / --hard の違いと使い分け
  • git commit --amend で直前のコミットを修正する方法
  • 公開済みブランチで安全に取り消す git revert の使い方
  • 複数コミットをまとめて取り消す・特定のコミットだけ取り消すテクニック
  • 誤って--hardしたときにgit reflogで救済する手順
  • やってはいけない落とし穴(共有ブランチでの履歴改変・force push事故)
スポンサーリンク

まず確認:2つの質問で取り消し方が決まる

取り消し方法を選ぶときに迷わないコツは、「pushしたか?」「変更は残したいか?」の2つの質問に答えることです。

  1. push済みか? → Yesならrevert、Noならresetまたはamend
  2. ファイルの変更は残したいか? → 残すなら--soft--mixed、破棄なら--hard

この2軸に「メッセージだけ直したい」「ファイルを追加し忘れた」などの頻出パターンを加えた早見表が以下です。最初にgit statusgit log --oneline -5で現状を把握してから選びましょう。

状況 推奨コマンド 履歴改変
直前のコミットメッセージだけ直したい git commit --amend あり(未pushのみ安全)
直前のコミットを取り消し、変更はそのまま残す git reset --soft HEAD~1 あり(未pushのみ)
直前のコミットを取り消し、ステージングも解除したい git reset --mixed HEAD~1 あり(未pushのみ)
直前のコミットを取り消し、変更もすべて破棄する git reset --hard HEAD~1 あり(未pushのみ)
push済みコミットを共有環境で取り消したい git revert <SHA> なし(安全)
ファイル追加を忘れて先にコミットした git add && git commit --amend --no-edit あり(未pushのみ)
複数の古いコミットをまとめて取り消したい git reset HEAD~N または git rebase -i あり(未pushのみ)

ポイント:push済みや他メンバーが取得済みのブランチでは、原則としてrevertを使います。resetcommit --amend履歴を書き換えるため、共有後に行うと他の開発者の環境を破壊します。

取り消し前に必ず現状を確認する

取り消し作業で失敗する最大の原因は「何を取り消そうとしているか分かっていないまま操作する」ことです。まず以下のコマンドで、コミット履歴と作業ツリーの状態を把握しましょう。

現状確認コマンド
# 直近5件のコミット履歴をSHAとメッセージで表示
git log --oneline -5

# 変更がステージに上がっているか、未コミットかを確認
git status

# 指定コミットの差分を事前に確認
git show <SHA>

# ブランチがリモートと比べて何コミット進んでいるか確認
git log --oneline origin/main..HEAD

特に重要なのは「このコミットはpush済みか?」という確認です。リモートに出ていない(origin/main..HEADに含まれる)コミットはresetで自由に消せますが、push済みの場合はrevertで打ち消すのが原則です。

直前のコミットを取り消して変更を残す(–soft)

「コミットは取り消したいが、変更したファイルは手元に残してもう一度やり直したい」というときはgit reset --soft HEAD~1を使います。コミットは消えますが、ファイルの変更はステージング(git add済み)の状態のまま残るため、ファイルの選び直しやメッセージの書き直しがすぐできます。

git reset –soft の使用例
# 直前のコミットを1件取り消す(変更はindexに残る)
git reset --soft HEAD~1

# 状態を確認:変更が「Changes to be committed」に残っていればOK
git status

# 必要に応じてファイルを追加・除外してから、新しいメッセージで再コミット
git reset HEAD some_unwanted_file.txt   # ステージから外すだけ
git commit -m "修正後の正しいコミットメッセージ"

ポイント:--softはコミットの「巻き戻し」であり、変更内容は消しません。コミットを小分けに分割したい・メッセージを整えたい・ファイル範囲を見直したい、といった場合の第一選択肢です。

直前のコミットを取り消してステージングも解除する(–mixed)

git reset --mixed HEAD~1(オプション省略時のデフォルト)は、コミットを取り消したうえでステージングも解除します。ファイルの変更自体はワーキングツリーに残るため、git addをやり直しながらより慎重に分割コミットしたいときに向いています。

git reset –mixed の使用例
# --mixed はデフォルトなので省略可能
git reset HEAD~1

# 状態確認:「Changes not staged for commit」に変更が残っていればOK
git status

# 必要なファイルだけ add してから再コミット
git add src/main.py
git commit -m "main.py の修正のみをコミット"

–soft と –mixed の違い

  • –soft:コミットだけ取り消す。git add済みの状態は維持
  • –mixed:コミットもステージングも取り消す。git addからやり直す
  • –hard:コミット・ステージング・ワーキングツリーすべて破棄

直前のコミットを取り消して変更も完全に破棄する(–hard)

git reset --hard HEAD~1はコミットに加えてワーキングツリーの変更まで完全に消去します。「直近の変更が本当に不要・初期化してやり直したい」ときだけ使う強力なコマンドです。

git reset –hard の使用例
# 直前のコミットと変更を完全に破棄
git reset --hard HEAD~1

# 2件前まで戻したい場合
git reset --hard HEAD~2

# 特定のSHAまで戻す
git reset --hard a1b2c3d

注意:--hardは未コミットの変更も消えます。まだgit addしていない編集中のファイルもすべて失うため、作業中のファイルがある場合は先にgit stashで退避するか、本当に破棄してよいか確認してから実行してください。

もし--hardで誤って変更を消してしまった場合は、この記事のreflogによる救済セクションを参照してください。直近のHEAD位置はGitが履歴として保持しているため、復元できる可能性があります。

コミットメッセージを直したい(–amend)

「コミット内容は正しいけれどメッセージをtypoした」という軽微なケースはgit commit --amendが最適です。コミットを作り直すのではなく、直前のコミットを書き換えます。

git commit –amend の使用例
# 直前のコミットメッセージをエディタで編集
git commit --amend

# メッセージを直接指定して書き換える
git commit --amend -m "正しいコミットメッセージ"

# ファイル追加を忘れたときは、add してから --no-edit で上書き
git add forgotten_file.py
git commit --amend --no-edit

注意:--amendはSHAが変わるため実質的に履歴の書き換えです。push前ならそのままgit pushできますが、push済みの場合はgit push --force-with-leaseが必要になります。共有ブランチではメッセージ修正でもrevertで新しいコミットを追加する方が安全です。

コミットメッセージ修正を詳しく知りたい場合は、【Git】コミットメッセージの変更方法も参考になります。

push済みのコミットを安全に取り消す(revert)

リモートにpush済みのコミットや、他の開発者が既に取得しているコミットを取り消すときはgit revertが正解です。履歴を改変せず、対象コミットの変更を打ち消す新しいコミットを追加します。他メンバーのローカルと衝突しないため、共有ブランチで安全に使えます。

git revert の使用例
# 直前のコミットを打ち消す
git revert HEAD

# 特定のコミット(SHA指定)を打ち消す
git revert a1b2c3d

# 複数コミットをまとめて打ち消す(範囲指定)
git revert a1b2c3d^..f4e5d6a

# コミットを作らず、変更だけ適用する(自分でまとめてコミットしたい場合)
git revert --no-commit HEAD~3..HEAD
git commit -m "revert: 直近3コミットの変更を打ち消し"

# マージコミットを取り消す場合は -m で残す親を指定
git revert -m 1 <マージコミットSHA>

ポイント:revert実行中にコンフリクトが起きたら、git statusで衝突ファイルを確認 → 手動で修正 → git addgit revert --continueで続行します。途中で中止するならgit revert --abortです。

マージコミットの取り消しには注意点が多いため、詳細は【Git】mergeコミットを取り消して履歴を元に戻す方法を参照してください。

複数コミットをまとめて取り消す

直近N件のコミットをまとめて取り消したい場合は、HEADからの相対指定か、戻したいコミットのSHAを直接指定します。

複数コミットの取り消し
# HEADから3件分のコミットを取り消す(変更はワーキングツリーに残る)
git reset HEAD~3

# 3件分を完全に破棄
git reset --hard HEAD~3

# 特定のコミットの直前まで戻す(そのSHAに戻る)
git reset --hard a1b2c3d

# インタラクティブに選んで取り消す・まとめる(途中のコミットだけdropしたい等)
git rebase -i HEAD~5

git rebase -iは起動後のエディタでpickdropに変えれば特定のコミットだけピンポイントで削除でき、squashにすれば隣のコミットに統合できます。特定のコミットまで戻したい場合の詳細は【Git】特定のコミットまで戻す方法、pushしてしまった後の取り消しは【Git】push を取り消す方法に専用解説があります。

誤って消したコミットをreflogで救う

git reset --hardで大事な変更を消してしまった、間違ったコミットまで戻してしまった——そんなときはgit reflogで救済できる可能性があります。Gitは約90日間、HEADの移動履歴をローカルに保持しています。

reflog による復元
# HEADの移動履歴を一覧表示
git reflog

# 出力例:
#   a1b2c3d HEAD@{0}: reset: moving to HEAD~1
#   f4e5d6a HEAD@{1}: commit: 消したくなかった大事な修正
#   9876543 HEAD@{2}: commit: その前の作業

# 消してしまったコミットのSHA(例: f4e5d6a)を指定して復元
git reset --hard f4e5d6a

# あるいは HEAD@{N} 記法でも指定可能
git reset --hard HEAD@{1}

ポイント:reflogは「ローカルリポジトリ上でGitが認識したHEADの動き」を記録しています。削除直後であればほぼ確実に救済できるので、--hardで失敗したと気づいたら他の操作をする前にgit reflogを確認してください。

reset の3つのモードを比較する

違いを整理しておくと、どれを使うべきか瞬時に判断できます。「HEADの移動」「indexの変更」「ワーキングツリーの変更」の3階層のどこまで巻き戻すかが違いです。

モード HEAD ステージ(index) ワーキングツリー 主な用途
--soft 移動 保持 保持 コミットを分割・メッセージ修正
--mixed(既定) 移動 リセット 保持 addをやり直したい
--hard 移動 リセット リセット 変更ごと完全に破棄

この違いを押さえると、「変更を残したいかどうか」「ステージに戻したいか」の2軸ですぐに選べるようになります。revertとの使い分けについては【Git】revertとresetの違いと使い分けで詳しく解説しています。

やってはいけない落とし穴

コミット取り消しで現場が混乱する代表的な失敗パターンです。事前に頭に入れておくだけで事故を防げます。

共有ブランチで reset + force push する

mainやdevelopなど複数人が触るブランチgit reset --hardを使い、git push --forceすると、他メンバーのローカルに残っていたコミットが消えたり、ビルドが壊れたりします。共有ブランチで取り消すならrevertを使うこと。

未コミットの作業を残したまま –hard する

編集中のファイルがあるままgit reset --hardを実行すると、未コミットの変更がすべて消えて戻せなくなります(reflogにも残らない)。迷ったらgit stashで退避してから実行しましょう。

push済みを –amend して単純な git push する

push後にgit commit --amendするとローカルとリモートで履歴が食い違い、普通のgit pushnon-fast-forwardで拒否されます。強制pushが必要な場面ではgit push --force-with-leaseを使い、単純な--forceは避けてください(他人のpushを上書きする事故が起きます)。

reflog の期限を過ぎた後に気づく

reflogはデフォルト90日で自動clean upされます。--hardで消した後に数ヶ月経って復元しようとしても手遅れです。重要な作業はこまめにpushするか、ブランチを切って残しておくのが安全策です。

merge コミットを何も考えずに revert する

マージコミットに対しては-m <親番号>オプションが必須です。指定しないと「どちらの親を基準に戻すか」が決まらずエラーになります。詳細はmergeコミットの取り消しガイドを参照。

実践:よくあるシナリオと手順

シナリオ① 機密情報を誤ってコミットしたがまだpushしていない

まず該当のコミットを取り消し、機密情報を除いてから再コミットします。

未pushで機密を混入させた場合
# コミットは取り消し、変更は手元に残す
git reset --mixed HEAD~1

# 機密ファイルを .gitignore に追加
echo "config/secret.env" >> .gitignore

# 機密ファイルを除外して再コミット
git add -A
git commit -m "feat: 設定ファイルの追加(secret.envは除外)"

シナリオ② push済みコミットを打ち消したい

履歴は残したまま、そのコミットの変更だけを元に戻す形が安全です。

push済みコミットの打ち消し
# 打ち消したいコミットのSHAを確認
git log --oneline

# revertで打ち消しコミットを作成
git revert a1b2c3d

# 打ち消しコミットをpush
git push origin main

シナリオ③ 直近3コミットを1つにまとめたい

reset --softで3件まとめて取り消し、1件に再コミットすると簡単です。

3コミットを1つに統合
# 直近3件を取り消し、変更はステージに残す
git reset --soft HEAD~3

# まとめた1つのコミットを作成
git commit -m "feat: 認証機能を追加(旧3コミットを統合)"

より細かく選び直したい場合はgit rebase -i HEAD~3pick/squash/dropを指定します。

よくある質問

Qreset と revert、結局どちらを使えばいい?
A未pushで自分しか触っていないならreset、push済みや共有ブランチならrevertが基本です。resetは履歴を書き換え、revertは打ち消しコミットを追加するという点で根本的に違います。
QHEAD~1 と HEAD^ は同じ意味?
A親コミットが1つだけの通常コミットでは同じ意味です。HEAD~Nは「N個前の先祖」、HEAD^Nは「N番目の親」を指します。マージコミットで2つの親を区別したいときだけ^系を使います。
Qreset –hard で消した変更は本当に戻せないの?
Aコミット済みの変更ならgit reflogで復元できます(90日以内)。ただし未コミットの変更(addもしていない編集中のファイル)は--hardで完全に失われます。不安なら先にgit stashで退避してから実行するのが安全です。
Qgit revert でコンフリクトが出たらどうすれば?
A通常のマージコンフリクトと同じ手順で解決します。git statusで衝突ファイルを確認 → 手動で編集 → git addgit revert --continueで完了。中止したい場合はgit revert --abortで元に戻せます。
Qpush後に amend してしまい、push できない
A個人用ブランチであればgit push --force-with-leaseで安全に強制pushできます。これは「リモートが自分の想定通りの状態なら」強制するオプションで、他人のpushを知らずに上書きする事故を防げます。共有ブランチではrevertに切り替えてください。
Q特定のファイルだけ前の状態に戻したい
Aコミット全体ではなく特定ファイルだけを戻したい場合はgit checkoutgit restoreを使います。詳しくは特定のファイルだけ前のコミットに戻す方法で解説しています。

関連記事

まとめ

  • 取り消し前に必ずgit statusgit log --onelineで現状把握
  • 未pushならreset系:--softは変更保持、--mixedはステージ解除、--hardは完全破棄
  • push済み・共有ブランチならrevertで打ち消しコミットを追加する
  • メッセージ修正・ファイル追加忘れはgit commit --amendが便利(未pushのみ)
  • 誤って--hardしてもgit reflogで救済できる可能性がある
  • 共有ブランチでのforce pushと--amendはチーム全体の事故になりやすいので避ける

コミットの取り消しは「何を」「どこまで」戻したいかを意識すれば、怖いコマンドではなく日常的に使える便利な道具になります。今回の判断表を手元に置き、状況に応じた最小限の取り消しで安全にGitを使いこなしましょう。