git commit 取り消し|git reset の使い方と soft / mixed / hard の違い

コマンドリファレンス

Gitでコミットしてしまった後に「やり直したい」と思う場面は多くあります。コミットメッセージを間違えた、余分なファイルを含めてしまった、作業途中でコミットしてしまったなど、状況はさまざまです。

本記事では、git commit の取り消し・修正に使う git resetgit commit --amend を中心に、soft / mixed / hard の違いや事故を防ぐ注意点まで整理します。

よく使うコマンド一覧

まず、コミット取り消し・修正でよく使うコマンドをまとめます。詳細は各セクションで解説します。

# 直前コミットを取り消し(変更はステージングに残す)
git reset --soft HEAD^

# 直前コミットを取り消し(変更はワーキングツリーに残す)
git reset --mixed HEAD^
git reset HEAD^          # --mixed がデフォルト

# 直前コミットを取り消し(変更ごと完全に削除)
git reset --hard HEAD^

# 2つ前に戻す場合
git reset --hard HEAD~2

# 特定のコミットまで戻す
git reset --hard <コミットID>

# 直前コミットのメッセージだけ修正
git commit --amend -m "新しいメッセージ"

# 直前コミットにファイルを追加してやり直す
git add 追加ファイル
git commit --amend --no-edit

1. git reset とは

git reset は、HEADの位置(コミット履歴のポインタ)を指定したコミットまで移動させるコマンドです。移動先を HEAD^(直前のコミット)にすることで、直前のコミットを取り消せます。

# 基本的な書き方
git reset [オプション] <戻り先>

# HEAD^ : 直前のコミット(HEAD~1 と同じ意味)
# HEAD~2 : 2つ前のコミット
# <コミットID> : 特定のコミット

オプションによって、取り消したコミットの変更内容をどこに残すかが異なります。

2. reset –soft / –mixed / –hard の違い

3つのオプションの違いを表で整理します。

オプションコミットステージング(インデックス)ワーキングツリー(ファイル)
--soft取り消すそのまま残るそのまま残る
--mixed(デフォルト)取り消す取り消すそのまま残る
--hard取り消す取り消す取り消す(削除)

2-1. –soft:コミットだけ取り消す

コミットを取り消しつつ、変更内容はステージング済みの状態で残します。「コミットメッセージを直したい」「複数のコミットをまとめて1つにしたい」ときに使います。

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

実行後は git status で確認すると、変更ファイルが「Changes to be committed」(コミット予定)の状態になっています。そのまま git commit -m "正しいメッセージ" を実行すればやり直せます。

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

コミットとステージングを取り消し、変更内容はワーキングツリー(ファイルの変更自体)に残します。--mixed はデフォルトなので省略可能です。「コミット自体をなかったことにして、どのファイルをコミットに含めるか再選択したい」ときに使います。

# 直前コミットを取り消し(変更はワーキングツリーに残る)
git reset HEAD^          # --mixed がデフォルト
git reset --mixed HEAD^  # 同じ意味

実行後は git status で確認すると、変更ファイルが「Changes not staged for commit」(未ステージング)の状態になっています。

2-3. –hard:コミットも変更も完全に取り消す

コミット・ステージング・ファイルの変更すべてを削除します。「そのコミット以降の変更をすべて捨てて元に戻したい」ときに使います。

# 直前コミットを変更ごと完全に取り消す
git reset --hard HEAD^

# 特定のコミットまで完全に戻す
git reset --hard <コミットID>

注意: --hard で取り消した変更はワーキングツリーから削除されるため、元に戻せません。実行前に本当に不要な変更か確認してください。

3. 直前コミットを修正する(git commit –amend)

git commit --amend は、直前のコミットを修正するコマンドです。コミット履歴を1件追加するのではなく、直前のコミットそのものを書き換えます。

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

コミット内容(ファイルの変更)はそのままで、メッセージだけ変えたいときに使います。

# コミットメッセージを変更する
git commit --amend -m "修正後のコミットメッセージ"

# エディタを開いてメッセージを編集する
git commit --amend

3-2. ファイルも追加してコミットをやり直す

「追加し忘れたファイルがあった」「コミット前に小さな修正を入れたい」という場合は、ファイルをステージングした後で --amend を実行します。

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

# メッセージはそのままでコミットをやり直す
git commit --amend --no-edit

# メッセージも変える場合
git commit --amend -m "新しいメッセージ"

--no-edit を付けると、エディタが開かずメッセージをそのまま引き継げます。

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

操作使うコマンド用途
直前コミットのメッセージを修正git commit --amend最速で修正できる
直前コミットにファイルを追加git add + git commit --amend追加し忘れたときに便利
複数コミットをまとめたいgit reset --soft HEAD~Nスカッシュ的な用途に向く
コミットを完全にやり直したいgit reset --mixed HEAD^ファイル変更を残しつつ再構成

4. 事故を防ぐ注意点

4-1. –hard は実行前に必ず確認する

git reset --hard で取り消したワーキングツリーの変更は、基本的に復元できません。実行前に git statusgit diff で現在の状態を確認する習慣をつけましょう。

# 実行前に状態を確認する
git status
git diff

# それでも戻したい場合
git reset --hard HEAD^

4-2. プッシュ済みのコミットには使わない

git resetgit commit --amend は、コミット履歴を書き換えます。すでにリモートへプッシュ済みのコミットに使うと、他のメンバーのリポジトリとの履歴が食い違い、チームに大きな混乱をもたらします。

# プッシュ前のコミットにのみ使う(ローカルだけに存在するコミット)
git reset --soft HEAD^   # OK:まだプッシュしていない場合

# プッシュ済みの場合は git revert を使う
git revert HEAD          # コミット取り消しのコミットを追加(履歴を書き換えない)

4-3. git reflog で誤操作から復元できる

--hard で誤って取り消してしまっても、直後であれば git reflog でコミットIDを確認し、復元できることがあります。

# reflog でコミット履歴を確認
git reflog

# 出力例:
# a1b2c3d HEAD@{0}: reset: moving to HEAD^
# e4f5g6h HEAD@{1}: commit: 作業内容
# ...

# 消えたコミット(e4f5g6h)に戻す
git reset --hard e4f5g6h

git reflog はローカルの操作履歴を記録しているため、--hard で削除したコミットも一定期間は参照できます。

4-4. 作業中のファイルは stash でバックアップ

reset の前に未コミットの作業内容をバックアップしたい場合は git stash を使います。

# 作業中の変更を一時退避
git stash

# reset を実行
git reset --hard HEAD^

# 必要なら退避した変更を戻す
git stash pop

5. よくある疑問

HEAD^ と HEAD~1 は同じ意味か

同じ意味です。HEAD^ は直前のコミット(1つ前)を指します。2つ前は HEAD^^ または HEAD~2、3つ前は HEAD~3 のように書きます。

reset –mixed と reset –soft はどちらを使えばいいか

「コミットをやり直したいが、何をステージするか再選択したい」なら --mixed、「コミットを取り消してすぐにコミットし直す(ファイル選択は変えない)」なら --soft が向いています。迷ったら --mixed(デフォルト)を使えばファイルは消えないので安全です。

git revert と git reset の違いは何か

git reset はコミット履歴を書き換えます。一方 git revert は「取り消しコミット」を新たに追加することで変更を打ち消します。プッシュ済みのコミットを取り消す場合は git revert を使い、履歴を書き換えないのが原則です。

amend したらプッシュできなくなった

git commit --amend はコミット履歴を書き換えるため、プッシュ済みのコミットに使うとリモートとの履歴が食い違い、通常のプッシュが拒否されます。個人ブランチであれば git push --force-with-lease で上書きできますが、チームで使うブランチでは行わないでください。

コミット取り消し後にリモートと同期するには

ローカルでコミットを取り消した後、リモートと同期するには git pull --rebase または git fetch + git reset が必要になる場合があります。個人ブランチでなければ、チームに影響が出るため慎重に判断してください。

まとめ

git commit 取り消し・git reset の使い方をまとめます。

  1. –soft: コミットだけ取り消し。変更はステージング済みで残るため、コミットをすぐにやり直せる。
  2. –mixed(デフォルト): コミットとステージングを取り消し。変更はファイルに残るため、git add からやり直せる。
  3. –hard: コミット・ステージング・ファイル変更すべてを削除。元に戻せないため、実行前に必ず確認する。
  4. git commit –amend: 直前コミットのメッセージ修正やファイル追加に便利。プッシュ済みには使わない。
  5. プッシュ済みには git revert: 共有ブランチのコミット取り消しは履歴を書き換えない git revert を使う。
  6. 誤操作は git reflog で復元: –hard で消しても git reflog からコミットIDを探して復元できる場合がある。
Bash玄

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

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

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

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

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

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

Bash玄をフォローする

コメント