Git 直前のコミットに戻す完全ガイド – 状況別の安全な戻し方

git

「直前のコミットに戻したい」と思った時、実は3つの異なる意味があることをご存知ですか?

  1. 作業内容を直前のコミット時点にリセット(今の変更を破棄)
  2. 最新のコミットを取り消す(コミット自体をなかったことに)
  3. 直前のコミットの状態を復元(新しいコミットとして記録)

それぞれ使うコマンドも、影響範囲も違います。

この記事では、あなたが本当にやりたい「戻す」を実現する方法を、安全性を重視しながら詳しく解説します。間違えてデータを失わないよう、必ずバックアップを取ってから実行しましょう。


スポンサーリンク
  1. クイック診断:どの「戻す」を使うべき?
    1. あなたの状況を選んでください
  2. ケース1:作業中の変更を破棄して直前のコミットに戻す
    1. 現在の変更をすべて破棄
    2. ステージングエリアの変更も含めて破棄
    3. 新規作成ファイル(untracked)も削除
  3. ケース2:最新のコミットを取り消す
    1. コミットだけ取り消す(変更は残す)
    2. コミットとステージングを取り消す(変更は残す)
    3. コミットも変更も完全に取り消す(危険!)
  4. ケース3:プッシュ済みのコミットを安全に戻す
    1. git revert で打ち消しコミットを作成
    2. マージコミットを revert する
  5. ケース4:特定のファイルだけ前の状態に戻す
    1. 直前のコミットからファイルを復元
    2. 複数ファイルを選択的に戻す
  6. 実践例:よくあるシナリオと解決法
    1. シナリオ1:実験的な変更を全部なかったことにしたい
    2. シナリオ2:本番環境にバグをデプロイしてしまった
    3. シナリオ3:間違ったブランチでコミットした
    4. シナリオ4:複数のコミットをまとめてやり直したい
  7. 安全対策:データを失わないために
    1. 作業前のバックアップ
    2. 復元可能な期間
    3. dry-run(実行前の確認)
  8. コマンド早見表
    1. 🔄 変更を破棄
    2. ↩️ コミットを取り消す
    3. 📄 ファイル単位で戻す
    4. 🔍 状態確認
  9. トラブルシューティング
    1. エラー:Your local changes would be overwritten
    2. エラー:Cannot revert because of uncommitted changes
    3. 間違えてreset –hardしてしまった
  10. ベストプラクティス
    1. 1. 段階的なアプローチ
    2. 2. エイリアスの活用
    3. 3. チーム開発での注意点
  11. まとめ:状況に応じた適切な「戻す」を選ぼう

クイック診断:どの「戻す」を使うべき?

あなたの状況を選んでください

Q: 何を戻したいですか?
│
├─ 【作業中のファイルを直前のコミット状態に戻したい】
│   └─ git restore . または git checkout .
│
├─ 【さっきしたコミットを取り消したい】
│   ├─ まだプッシュしていない
│   │   └─ git reset HEAD~1
│   └─ もうプッシュした
│       └─ git revert HEAD
│
└─ 【特定のファイルだけ前の状態に戻したい】
    └─ git restore ファイル名

ケース1:作業中の変更を破棄して直前のコミットに戻す

現在の変更をすべて破棄

状況: ファイルを編集したけど、やっぱり直前のコミットの状態に戻したい

⚠️ 警告:保存していない変更は完全に失われます

方法1:git restore を使う(Git 2.23以降推奨)

# すべてのファイルを直前のコミット状態に戻す
git restore .

# 特定のファイルだけ戻す
git restore ファイル名.txt

# 複数ファイルを指定
git restore file1.txt file2.txt

# ディレクトリ全体を戻す
git restore src/

方法2:git checkout を使う(従来の方法)

# すべてのファイルを戻す
git checkout -- .

# 特定のファイルを戻す
git checkout -- ファイル名.txt

# HEADを明示的に指定
git checkout HEAD -- .

ステージングエリアの変更も含めて破棄

# ステージング(git add済み)も含めて全部破棄
git reset --hard HEAD

# より安全:まずステージングから除外してから破棄
git restore --staged .  # ステージングから除外
git restore .           # 変更を破棄

新規作成ファイル(untracked)も削除

# 確認:削除されるファイルを表示
git clean -n

# 実行:untrackedファイルを削除
git clean -f

# ディレクトリも含めて削除
git clean -fd

# .gitignoreされているファイルも削除(危険!)
git clean -fdx

ケース2:最新のコミットを取り消す

コミットだけ取り消す(変更は残す)

状況: コミットメッセージを間違えた、コミットし忘れたファイルがある

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

# 確認
git status
# Changes to be committed: (ステージングに残っている)

使用例:

# コミットをやり直す流れ
git reset --soft HEAD~1        # コミット取り消し
git add 忘れたファイル.txt      # ファイル追加
git commit -m "正しいメッセージ" # 再コミット

コミットとステージングを取り消す(変更は残す)

# デフォルトの動作(--mixedと同じ)
git reset HEAD~1

# または明示的に
git reset --mixed HEAD~1

# 確認
git status
# Changes not staged for commit: (作業ディレクトリに残る)

コミットも変更も完全に取り消す(危険!)

⚠️ 警告:このコマンドは変更を完全に削除します

# すべてを直前のコミット状態に戻す
git reset --hard HEAD~1

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

# 特定のコミットに戻す
git reset --hard abc1234

ケース3:プッシュ済みのコミットを安全に戻す

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

これが最も安全な方法です

# 直前のコミットを打ち消す新しいコミットを作成
git revert HEAD

# コミットメッセージを自動で作成
git revert HEAD --no-edit

# 複数のコミットを順番に打ち消す
git revert HEAD~3..HEAD

# 特定のコミットを打ち消す
git revert abc1234

実行例:

$ git log --oneline
abc1234 (HEAD -> main) バグのあるコード追加
def5678 正常なコード

$ git revert HEAD
[main xyz9876] Revert "バグのあるコード追加"

$ git log --oneline
xyz9876 (HEAD -> main) Revert "バグのあるコード追加"
abc1234 バグのあるコード追加
def5678 正常なコード

マージコミットを revert する

# マージコミットの場合は親を指定
git revert -m 1 HEAD

# -m 1:1番目の親(通常はメインブランチ)を保持
# -m 2:2番目の親(マージされたブランチ)を保持

ケース4:特定のファイルだけ前の状態に戻す

直前のコミットからファイルを復元

# 方法1:restore を使う(推奨)
git restore ファイル名.txt

# 方法2:checkout を使う
git checkout HEAD -- ファイル名.txt

# 方法3:特定のコミットから復元
git restore --source HEAD~2 ファイル名.txt

複数ファイルを選択的に戻す

# 対話的に選択
git checkout -p HEAD -- .

# パターンマッチング
git restore '*.js'           # すべてのJSファイル
git restore 'src/**/*.css'   # srcディレクトリ以下のCSSファイル

実践例:よくあるシナリオと解決法

シナリオ1:実験的な変更を全部なかったことにしたい

# 状況確認
git status
git diff

# 解決法1:すべて破棄(未コミットの場合)
git restore .
git clean -fd

# 解決法2:コミット済みの場合
git reset --hard HEAD~1  # 直前のコミット前に戻る

シナリオ2:本番環境にバグをデプロイしてしまった

# 緊急対応:revertで即座に修正
git revert HEAD --no-edit
git push origin main

# その後、落ち着いて原因調査と修正
git checkout -b fix-bug
# バグ修正作業...

シナリオ3:間違ったブランチでコミットした

# 現在:wrong-branchにいる
git log --oneline
# abc1234 (HEAD -> wrong-branch) 間違えてコミット

# 1. 正しいブランチに移動
git checkout correct-branch

# 2. コミットを持ってくる
git cherry-pick abc1234

# 3. 間違ったブランチから削除
git checkout wrong-branch
git reset --hard HEAD~1

シナリオ4:複数のコミットをまとめてやり直したい

# 直近3つのコミットをやり直す
git reset --soft HEAD~3

# ファイルを整理
git add -p  # 対話的に選択

# 新しくコミット
git commit -m "機能Aを実装(リファクタリング済み)"

安全対策:データを失わないために

作業前のバックアップ

# 方法1:ブランチを作成
git branch backup-$(date +%Y%m%d-%H%M%S)

# 方法2:タグを付ける
git tag backup-before-reset

# 方法3:stashで退避
git stash save "作業前のバックアップ"

復元可能な期間

# reflogで過去の操作履歴を確認
git reflog

# 出力例
abc1234 HEAD@{0}: reset: moving to HEAD~1
def5678 HEAD@{1}: commit: 重要な変更
ghi9012 HEAD@{2}: commit: 初期コミット

# 間違えてresetした場合の復元
git reset --hard def5678  # HEAD@{1}の状態に戻る

dry-run(実行前の確認)

# cleanの確認
git clean -n  # 削除されるファイルを表示

# resetの影響確認
git log --oneline -5  # 現在の履歴
git log HEAD~1 --oneline -5  # reset後の履歴(予想)

# diffで変更内容確認
git diff HEAD HEAD~1  # 差分を確認

コマンド早見表

🔄 変更を破棄

# 作業中の変更を破棄
git restore .                    # すべて
git restore ファイル名           # 特定ファイル

# ステージングから除外
git restore --staged .

# 完全リセット(危険)
git reset --hard HEAD

↩️ コミットを取り消す

# ローカルのコミット取り消し
git reset --soft HEAD~1   # コミットのみ
git reset HEAD~1          # コミット+ステージング
git reset --hard HEAD~1   # すべて(危険)

# プッシュ済みを安全に取り消し
git revert HEAD

📄 ファイル単位で戻す

# 特定ファイルを復元
git restore ファイル名
git checkout HEAD -- ファイル名

# 特定コミットから復元
git restore --source HEAD~2 ファイル名

🔍 状態確認

git status              # 現在の状態
git log --oneline -5    # コミット履歴
git diff               # 変更内容
git reflog             # 操作履歴

トラブルシューティング

エラー:Your local changes would be overwritten

原因: 未コミットの変更がある

解決法:

# 選択肢1:変更を保存
git stash
git reset --hard HEAD~1
git stash pop

# 選択肢2:変更を破棄
git reset --hard HEAD~1

エラー:Cannot revert because of uncommitted changes

解決法:

# 変更をコミットまたはstash
git stash
git revert HEAD
git stash pop

間違えてreset –hardしてしまった

復元方法:

# reflogから探す
git reflog
# abc1234 HEAD@{1}: commit: 消えた重要なコミット

# 復元
git reset --hard abc1234

ベストプラクティス

1. 段階的なアプローチ

# ❌ いきなり危険なコマンド
git reset --hard HEAD~5

# ⭕ 段階的に確認
git log --oneline -5      # 履歴確認
git diff HEAD HEAD~5       # 差分確認
git reset --soft HEAD~5    # まずsoftで
# 問題なければ
git reset --hard HEAD~5

2. エイリアスの活用

# ~/.gitconfigに追加

[alias]

undo = reset –soft HEAD~1 unstage = restore –staged discard = restore backup = !git branch backup-$(date +%Y%m%d-%H%M%S)

使用例:

git undo     # 直前のコミット取り消し
git unstage  # ステージング解除
git discard  # 変更破棄
git backup   # バックアップブランチ作成

3. チーム開発での注意点

# ❌ 共有ブランチでforce push
git reset --hard HEAD~1
git push -f  # 危険!

# ⭕ revertを使う
git revert HEAD
git push  # 安全

まとめ:状況に応じた適切な「戻す」を選ぼう

直前のコミットに戻す方法は、状況によって使い分けが必要です。

重要なポイント:

作業中の変更を破棄

  • git restore . が最もシンプル
  • 新規ファイルも消すなら git clean -f

コミットを取り消す

  • ローカルなら git reset
  • プッシュ済みなら git revert

安全性を重視

  • 常にバックアップを取る
  • --hard は最終手段
  • チーム開発では revert を使う

困ったときは

  • git reflog で履歴を確認
  • ほとんどの操作は取り消し可能

最初は慎重に、慣れてきたら効率的に。この記事を参考に、安全にGitを使いこなしてください!

Safe Git Life! 🛡️


クイックリファレンス:

  • 変更破棄:git restore .
  • コミット取り消し:git reset HEAD~1
  • 安全な取り消し:git revert HEAD
  • 履歴確認:git reflog

コメント

タイトルとURLをコピーしました