間違えた時の取り消し方 — restore, reset, revert
学習目標
このレッスンを終えると、次のことができるようになります。
restore/reset/revertの使い分けを表で説明できる- 「push 済」と「push 前」で取り消し方が変わる理由を理解できる
git reflogで「うっかり消した commit」を救出できる
取り消しの 3 段階
Git の取り消し操作は どこまで進んだ作業を戻すか によって違う。
flowchart LR
W[作業ディレクトリ<br/>編集中] -->|git add| S[ステージング エリア]
S -->|git commit| L[ローカル リポジトリ]
L -->|git push| R[リモート<br/>GitHub]
W -.戻す.-> R1[git restore]
S -.戻す.-> R2[git restore --staged]
L -.戻す.-> R3[git reset]
R -.戻す.-> R4[git revert]
| 状態 | 取り消しコマンド | 戻せる範囲 |
|---|---|---|
編集したがまだ add してない |
git restore <ファイル> |
編集をなかったことに |
add したがまだ commit してない |
git restore --staged <ファイル> |
ステージから降ろす (編集は残る) |
| commit したがまだ push してない | git reset HEAD~1 |
commit を取り消す (ローカル安全) |
| push してしまった | git revert <ハッシュ> |
打ち消し commit を新たに作る (履歴は残す) |
ケース 1: 編集を破棄したい (まだ add 前)
# src/login.py を編集したが、やっぱり元に戻したい
git restore src/login.py
注意: 編集内容は完全消去。Ctrl+Z できない。事前に git diff で内容を確認してから実行する。
ケース 2: ステージから降ろしたい (add したけど commit する前)
git add src/login.py # add した
# やっぱりこの変更は次の commit に入れたくない
git restore --staged src/login.py
# → ステージから降りる。編集自体は残っている (作業ディレクトリにある)
ケース 3: commit を取り消したい (まだ push してない)
git log --oneline
# a1b2c3d (HEAD) fix: ログイン修正 ← これを取り消したい
# 9f8e7d6 feat: 検索機能追加
git reset HEAD~1
# → a1b2c3d の commit を解いて、編集内容は作業ディレクトリに戻る
reset の 3 モード
| モード | 効果 | いつ使う |
|---|---|---|
--soft |
commit だけ解く。編集はステージング エリアに残る | commit メッセージだけ書き直したい |
--mixed (デフォルト) |
commit と add を解く。編集は作業ディレクトリに残る | commit 分け直したい |
--hard |
commit・add・編集すべて消す。復元不可 | 完全になかったことにしたい (危険) |
⚠️
--hardは破壊的。本講座 01-02 の「人間が必須」操作。AI Agent に単独実行させない。
ケース 4: push 済の変更を打ち消す (revert)
# すでに push 済の a1b2c3d を打ち消したい
git revert a1b2c3d
# → 「a1b2c3d を打ち消す内容」の新規 commit が作られる
git push
revert は 履歴を消さず、打ち消し commit を追加する。他人がすでにその commit をベースに作業していてもトラブルにならない。
gitGraph
commit id: "init"
commit id: "9f8e7d6: 検索追加"
commit id: "a1b2c3d: ログイン修正"
commit id: "Revert: ログイン修正"
なぜ push 済を reset で消してはいけないか
git reset + git push --force でリモート履歴を書き換えると:
- 他のメンバーが既にその commit をベースに作業していた場合、全員の履歴が壊れる
- GitHub Actions / CI が混乱する
- リリースタグが指す commit が消えて本番デプロイ履歴が追えなくなる
→ 公開済の commit は revert で打ち消す。これが鉄則。
救出: git reflog — 消したと思った commit を取り戻す
git reset --hard で消したコミットも、約 90 日間は .git/ 内部に残っている。
git reflog
# 出力例:
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# d4e5f6a HEAD@{1}: commit: 大事な変更
# ...
# d4e5f6a を復元したい
git reset --hard d4e5f6a
reflog は「あなた自身がやった操作の履歴」。事故った時の最終救出ツール。まず焦って何かする前に git reflog を見る。
取り消し選択フロー
flowchart TD
Q[何かを取り消したい] --> P{push 済?}
P -->|No| L{commit 済?}
P -->|Yes| V[git revert で打ち消し commit]
L -->|No| A{add 済?}
L -->|Yes| R[git reset で戻す]
A -->|No| D[git restore で編集破棄]
A -->|Yes| U[git restore --staged で降ろす]
R -.失敗で消した?.-> RF[git reflog で救出]
振り返り
- 取り消しは 「進んだ段階」によってコマンドが変わる
- push 済は
revert(履歴を残して打ち消し)。reset+ force push は禁忌 git reflogは最後の救出策。事故ったらまず深呼吸してreflogを見る
次のセクションから、本コースの中心である branch (枝分かれ) と merge (統合) を学びます。
参考リンク
- Pro Git「やり直し」: https://git-scm.com/book/ja/v2/Git-の基本-作業のやり直し
git reflog公式: https://git-scm.com/docs/git-reflog
全 14 レッスンを、登録なしで無料で読めます。