Git reset hardと他のresetコマンドの違いを徹底解説|初心者向けガイド
Gitを使用していると、コミットを取り消したい場面に何度も遭遇します。その時に活躍するのがgit resetコマンドです。しかし、git reset --hard、git reset --soft、git reset --mixedの3つのオプションが存在し、どれを使うべきか迷う初心者も多いのではないでしょうか。
この記事では、これらのコマンドの違いを詳しく解説し、正しい使い方と危険性について説明します。
1. Git resetコマンドの原因の説明
Gitの3つのエリアを理解しよう
Git resetの違いを理解するには、まずGitの3つのエリアを知る必要があります。
- ワーキングディレクトリ(Working Directory):あなたがファイルを編集している場所
- ステージングエリア(Staging Area/Index):
git addでファイルを追加する場所 - Gitリポジトリ(Repository):
git commitで確定されたコミット履歴
この3つのエリアを図解すると以下のようになります:
ワーキングディレクトリ → ステージングエリア → Gitリポジトリ
(編集中) (git add) (git commit)
git resetの3つのオプションの違い
git resetコマンドには3つの主要なオプションがあり、それぞれが異なる範囲を「リセット」します。
- –soft:Gitリポジトリのみリセット(ステージングエリアとワーキングディレクトリは変更されない)
- –mixed:Gitリポジトリとステージングエリアをリセット(ワーキングディレクトリは変更されない)※デフォルト
- –hard:全てのエリアをリセット(ワーキングディレクトリも含めて完全にリセット)
では、各オプションの動作をさらに詳しく見ていきましょう。
2. 各resetオプションの解決手順
git reset –soft の場合
git reset --softを使用すると、コミット履歴は取り消されますが、変更したファイルはステージングエリアに残ります。
使用場面:コミットメッセージを修正したい時や、複数のコミットを1つにまとめたい時
手順:
- 現在のコミットハッシュを確認
git reset --soft HEAD~1を実行- ステージングエリアには変更が残る
- 必要に応じてコミットを作り直す
git reset –mixed の場合
git reset --mixedはGitのデフォルト動作です。コミット履歴とステージングエリアがリセットされますが、ワーキングディレクトリの変更は保持されます。
使用場面:ファイルの追加を取り消したい時、またはgit addを取り消したい時
手順:
git reset HEAD~1またはgit reset --mixed HEAD~1を実行- 変更したファイルはワーキングディレクトリに残る
- もう一度ファイルを編集して
git addし直す
git reset –hard の場合
git reset --hardは最も危険で、全てのエリアを完全にリセットします。ワーキングディレクトリの変更も失われます。
使用場面:すべての変更を完全に取り消したい時(但し、非常に慎重に使用すべき)
手順:
git reset --hard HEAD~1を実行- 全ての変更が失われ、1つ前のコミット状態に戻る
- ワーキングディレクトリも元の状態に戻される
3. コード例で理解する違い
実践的なシナリオ:複数のファイル変更を例に
以下のシナリオで各コマンドの動作を比較します。
$ git log --oneline
abc1234 (HEAD) 新機能の実装
def5678 バグ修正
ghi9012 初期コミット
現在、以下のファイルが存在するとします:
$ git status
On branch main
Changes not staged for commit:
modified: file1.txt
modified: file2.txt
Untracked files:
new_file.txt
シナリオ1:git reset –soft HEAD~1 を使った場合
$ git reset --soft HEAD~1
$ git status
On branch main
Changes to be committed:
modified: file1.txt
modified: file2.txt
Untracked files:
new_file.txt
結果:
- コミット「新機能の実装」は取り消された
- file1.txt と file2.txt の変更はステージングエリアに残る
- コミットメッセージを変更したり、ファイルを追加・削除してから再コミットできる
シナリオ2:git reset –mixed HEAD~1(またはgit reset HEAD~1)を使った場合
$ git reset HEAD~1
$ git status
On branch main
Changes not staged for commit:
modified: file1.txt
modified: file2.txt
Untracked files:
new_file.txt
結果:
- コミット「新機能の実装」は取り消された
- file1.txt と file2.txt の変更はワーキングディレクトリに残る(ステージングエリアからは削除)
- 再度
git addを実行する必要がある
シナリオ3:git reset –hard HEAD~1 を使った場合
$ git reset --hard HEAD~1
$ git status
On branch main
nothing to commit, working tree clean
結果:
- コミット「新機能の実装」は取り消された
- file1.txt と file2.txt の変更は完全に削除される
- ワーキングディレクトリは「バグ修正」のコミット時点の状態に戻る
- 変更内容は完全に失われるため、復元は困難
より実践的なコード例
実際の開発シーンでよく遭遇する例を見てみましょう:
#!/bin/bash
# 間違ったコミットを修正する流れ
# 1. 現在のログを確認
git log --oneline -5
# 2. 最後のコミットを取り消したいが、変更は保持したい場合
git reset --mixed HEAD~1
# または単に
git reset HEAD~1
# 3. 再度確認
git status
# 4. ファイルを正しく整理して再コミット
git add file1.txt
git commit -m \"修正済み:ファイル1のみをコミット\"
# 5. ファイル2は別のブランチで処理する場合
git checkout -b feature/file2-fix
git add file2.txt
git commit -m \"別タスク:ファイル2の修正\"
4. よくある間違いと対策
間違い1:git reset –hard を気軽に使用する
問題: 多くの初心者が理解せずに git reset --hard を使用し、重要な変更を失ってしまいます。
$ git reset --hard HEAD~1
# 数日間の作業が消えた...
対策:
git reset --hardを使用する前に、必ずgit statusとgit logで確認- 変更がある場合は、まず
git stashでセーフに保存 - 可能な限り
--softや--mixedを使用
$ # 安全な手順
$ git status # 現在の状態を確認
$ git log --oneline -5 # コミット履歴を確認
$ git diff HEAD~1 # 違いを確認
$ git reset --mixed HEAD~1 # 最初は--mixedで試す
間違い2:リモートリポジトリへのpush後にresetする
問題: すでにpushしたコミットに対して git reset を使用すると、チームメンバーとのコンフリクトが発生します。
$ git push origin main
$ git reset --hard HEAD~1 # 危険!他のメンバーが既にpullしている可能性
$ git push -f origin main # 強制push(チーム全体に影響)
対策:
- すでにpushしたコミットの場合は
git revertを使用 - どうしても必要な場合は、チームメンバーに事前に通知
- 共有ブランチでは
git reset --hardは避ける
$ # より安全な方法
$ git revert HEAD~1 # 新しいコミットで取り消しを記録
$ git push origin main # 安全にpush可能
間違い3:resetの対象コミットを誤指定する
問題: HEAD~1 と HEAD~2 を混同し、意図しないコミットまで取り消す。
$ git log --oneline
abc1234 (HEAD) コミット3
def5678 コミット2
ghi9012 コミット1
$ git reset --hard HEAD~2 # コミット2まで取り消される(コミット3だけではない)
対策:
- コミットハッシュで直接指定
- 実行前に必ず
git logで確認
$ # より明確な方法
$ git reset --hard ghi9012 # コミットハッシュで直接指定
$ # または
$ git reset --hard HEAD~1 # 1つ前に戻す(明確)
間違い4:削除されたコミットの復元を諦める
問題: git reset --hard で変更が消えたと思ってあきらめるユーザー
対策: Gitには git reflog コマンドで削除されたコミットを復元できる可能性があります。
$ # 削除されたと思ったコミットを復元
$ git reflog # すべての操作履歴を表示
abc1234 HEAD@{0}: reset: moving to HEAD~1
def5678 HEAD@{1}: commit: 間違ったコミット
ghi9012 HEAD@{2}: commit: 前のコミット
$ # 削除されたコミット(def5678)に戻す
$ git reset --hard def5678
5. まとめと推奨される使い分け
各コマンドの使い分けガイド
| コマンド | リセット範囲 | 使用場面 | 危険度 |
git reset --soft |
Gitリポジトリのみ | コミットメッセージの修正、複数コミットをまとめる | 低い |
git reset --mixed |
Gitリポジトリ+ステージング | ファイルの追加取り消し、再選別 | 低い |
git reset --hard |
全エリア | 完全にリセット(ローカルのみ) | 高い |
実務での推奨フロー
#!/bin/bash
# 推奨されるGitワークフロー
# 1. 現在の状態を常に確認
git status
git log --oneline -10
# 2. 間違ったコミットが見つかった場合
# ステップA:変更を保持したい場合
git reset --mixed HEAD~1 # またはgit reset HEAD~1
git diff # 変更内容を確認
# ステップB:コミットメッセージだけ修正したい場合
git reset --soft HEAD~1
git commit -m \"修正されたメッセージ\"
# ステップC:完全にやり直したい場合(ローカルのみ)
git reset --hard HEAD~1
# ステップD:既にpushした場合
git revert HEAD~1
git push origin main
# 3. 危険な操作の後は必ず確認
git log --oneline -10
git status
最後のアドバイス
Gitの reset コマンドは非常に強力ですが、同時に危険です。以下のポイントを忘れずに:
- 常に確認:実行前に必ず現在の状態を確認する
- ローカルのみ:pushする前に修正する
- 段階的に:いきなり
--hardは避け、--softや--mixedから試す - バックアップ:重要なブランチではstashで変更を保存
- reflogを活用:誤操作時は
git reflogで復元を試みる
git reset コマンドを正しく理解し、使い分けることで、Gitをより効果的に活用でき、誤操作のリスクも大幅に減らせます。

