取り消し操作フローチャート — restore / reset / revert / rm の選び方
「何を、どこから、どこまで戻すか」で取り消し系コマンドの使い分けが決まる。フローチャートで一目で選べるようにまとめる。

まずフローチャートで全体像
Git の「取り消し系」コマンドは restore reset revert rm と複数あり、初学者がもっとも迷う領域の 1 つです。
実は判断軸は次の 2 つしかありません。
- 取り消したい対象は何か?(ファイルの中身 / ステージング / コミット / ファイル追跡)
- 対象がすでに push 済みか?(履歴を書き換えてよいかの判断)
上のフローチャートは、この 2 つの質問だけで使うべきコマンドが 1 つに決まるようにまとめたものです。
詳細は以下のセクションで補足します。
A. 作業ツリーのファイル変更を捨てたい → git restore
まだ git add していないファイル変更を捨てたいときは git restore。
HEAD の状態(直前のコミット)に作業ツリーを戻します。
- 個別ファイル:
git restore file.txt - 複数まとめて:
git restore .(カレント以下すべて) - 別のコミットの内容を取り出す:
git restore --source HEAD~2 file.txt
reset --hard でも同じ結果になりますが、コミット位置まで動かしてしまうので意図しない巻き戻しが起きやすい。
「ファイルの変更だけ捨てたい」なら必ず restore を使います。
# 作業ツリーの変更を破棄
git restore file.txt
# 「やっぱり消したくない」と思ったら reflog で戻れない点に注意
# 大事な変更がある場合は git stash で先に退避する
git stash push -m "とりあえず退避"
git restore file.txtB. ステージング (git add) を取り消したい → git restore --staged
git add でステージしてしまった変更をステージから外したいときは git restore --staged <file>。作業ツリーの変更はそのまま残ります。
古い書き方として git reset HEAD <file> も同じ動作をしますが、初心者は reset の他のモード(--hard など)と混同しやすく事故の元なので、Git 2.23 以降は restore --staged に寄せるのが推奨です。
なお、新規追加したファイル(git add newfile.txt で追跡開始した直後)を「追跡しない状態」に戻したい場合は、restore --staged ではなく git rm --cached newfile.txt を使う点だけ注意してください。
# ステージから外す(作業ツリーは保持)
git restore --staged file.txt
# 新規追加ファイルを「未追跡」に戻す(rm --cached を使う)
git add newfile.txt
git rm --cached newfile.txtC. コミットを取り消したい — push 前なら git reset
まだ push していないコミットを取り消すなら git reset。
3 つのモードを目的で選びます。
| モード | 何が戻る? | 典型用途 |
|---|---|---|
--soft |
コミット位置だけ戻す。変更は ステージに残る | コミットメッセージを書き直したい |
--mixed(既定) |
コミットと add も取消。変更は 作業ツリーに残る | コミット範囲を切り直したい |
--hard |
コミットも変更も全部捨てる | 試作を破棄してまっさらにしたい |
--hard だけは破壊的なので、実行前に git stash で退避するか、最後の手段として使います。
詳細は git reset の実践的な使い方 と reset --hard で消した変更を復旧する を参照。
# 直前のコミットを取り消す(変更はステージに残す)
git reset --soft HEAD~1
# 直前 3 件をまとめて取り消し(変更は作業ツリーに残す)
git reset HEAD~3
# 完全に破棄(最後の手段)
git stash push -m "保険"
git reset --hard HEAD~1D. push 済みのコミットを取り消したい → git revert
すでに push してチームと共有しているコミットには reset を使わない。
履歴を書き換えると force push が必要になり、他のメンバーが取得済みのコミットと不整合を起こします。
代わりに git revert で「逆向きの変更を加える新しいコミット」を作ります。
履歴は前進したまま、結果として変更が打ち消されるので、共有ブランチでも安全です。
# push 済みコミットを安全に打ち消す
git revert <commit-hash>
# マージコミットを取り消す場合は親番号 -m を指定
git revert -m 1 <merge-commit-hash>
間違って force push を打ち込んでしまった場合の救出は reset --hard で消した変更を復旧する と git reflog を参照。
E. ファイルそのものを Git 管理から外したい → git rm
「変更を戻す」ではなく「ファイルそのものを Git の追跡対象から外す / 削除する」場合は git rm。
後者は .gitignore に入れ忘れて誤って追跡してしまったファイルを後から除外する定石です。
.env や node_modules/ を間違えて push してしまった場合の救出にも使います。
# 追跡を外しつつ .gitignore に追加
echo ".env" >> .gitignore
git rm --cached .env
git commit -m ".env を追跡対象から除外"
機密ファイルを誤ってコミットした場合の本格的な対処は 機密ファイルを誤ってコミットしたときの対処法 を参照。
よくある間違い — 似て非なる組み合わせ
| やりたいこと | 正しい | 間違いがち |
|---|---|---|
| 作業ツリーの変更だけ破棄 | git restore file |
git reset --hard で全部消えてしまう |
| ステージングだけ取消 | git restore --staged file |
git reset --hard で作業ツリーまで戻ってしまう |
| 新規追加した未コミットのファイルの追跡を外す | git rm --cached newfile |
git restore --staged newfile ではファイルが残ったままステージから外れない(場合あり) |
.env の追跡だけ外す(ファイルは残す) |
git rm --cached .env |
git rm .env でディスクからも消えてしまう |
| push 済みコミットを打ち消す | git revert <hash> |
git reset + push --force で他人の履歴を破壊 |
| 1 つ前のコミットメッセージを書き直す | git commit --amend または git reset --soft HEAD~1 |
git revert HEAD だと打ち消しコミットが残ってしまう |
関連トピック
- restore と reset の違い・使い分け — 2 コマンドの詳しい比較
- restore と rm の違い・使い分け — 「変更取消」と「ファイル削除」の対比
- git reset の実践的な使い方 — soft / mixed / hard の深掘り
- reset --hard で消した変更を復旧する — やらかし救出フロー
- 操作履歴から復旧する - git reflog — どんな取り消しからも戻せる最後の砦
- merge / rebase / cherry-pick の使い分け — 「進める」側のフローチャート
- ブランチ操作フローチャート — merge / rebase / reset の選び方
