git reset の使い分け完全ガイド:soft・mixed・hard の違いを理解する

Git を使った開発作業をしていると、コミット後に「あれ、間違えた!」と気づく瞬間がありますよね。そんなときに頼りになるのが git reset
コマンドです。しかし、--soft
、--mixed
、--hard
という 3 つのオプションがあって、どれを選べばよいのか迷ってしまうことも多いでしょう。
間違った選択をすると、大切な作業が消えてしまう可能性もあります。でも安心してください。今回は、これらの違いを図解でわかりやすく解説し、実際の開発現場で適切に使い分けられるようになるまでご案内いたします。
背景
Git のコミット管理の仕組み
Git の内部構造を理解することで、git reset
がなぜ必要で、どのように動作するのかが見えてきます。
Git は以下の 3 つのエリアでファイルの状態を管理しています。
mermaidflowchart LR
work[ワーキングディレクトリ] -->|git add| stage[ステージングエリア]
stage -->|git commit| repo[リポジトリ]
work -.->|git reset --hard| stage
stage -.->|git reset --mixed| repo
repo -.->|git reset --soft| history[コミット履歴]
図で理解できる要点:
- ワーキングディレクトリ:実際に編集しているファイル
- ステージングエリア:次のコミットに含める予定のファイル
- リポジトリ:コミット済みのファイル
ワーキングディレクトリ(Working Directory) 実際にファイルを編集している作業領域です。ここでコードを書いたり、設定ファイルを変更したりします。
ステージングエリア(Staging Area)
次のコミットに含めるファイルを一時的に保管する場所です。git add
コマンドでファイルをここに追加します。
javascript// 作業中のファイル example.js
function hello() {
console.log('Hello World!'); // 新しく追加した行
}
上記のファイルを編集後、以下のコマンドでステージングエリアに追加します。
bashgit add example.js
リポジトリ(Repository)
git commit
でステージングエリアの内容が永続的に保存される場所です。ここに保存された内容は Git の履歴として管理されます。
bashgit commit -m "Hello World関数を追加"
なぜリセット機能が必要なのか
開発作業では、以下のようなシチュエーションが頻繁に発生します。
コミットメッセージの間違い 急いでコミットしたときに、わかりにくいメッセージを書いてしまうことがあります。
bashgit commit -m "fix" # これでは何を修正したかわからない
間違ったファイルをコミット 本来コミットすべきでないファイル(設定ファイルやテスト用のダミーデータなど)を誤って含めてしまうケースです。
bashgit add . # 全ファイルを追加
git commit -m "機能追加" # 不要なファイルも含まれている
実装のやり直し 一度コミットしたものの、別のアプローチで実装し直したい場合があります。
このような状況で、安全に過去の状態に戻るために git reset
が必要になります。
git reset の基本概念
git reset
は指定したコミットの状態まで戻すコマンドです。重要なのは「どこまで戻すか」を 3 つのオプションで制御できる点です。
以下の図は、リセット前後の状態変化を示しています。
mermaidflowchart TB
subgraph before[リセット前]
b1[コミットA] --> b2[コミットB] --> b3[コミットC HEAD]
b4[ワーキングディレクトリ:変更あり]
b5[ステージングエリア:変更あり]
end
subgraph after[リセット後 git reset --soft HEAD~1]
a1[コミットA] --> a2[コミットB HEAD]
a4[ワーキングディレクトリ:変更あり]
a5[ステージングエリア:変更あり]
end
before --> after
図で理解できる要点:
- HEAD はカレントブランチの最新コミットを指すポインタ
HEAD~1
は 1 つ前のコミットを表す- リセットによりコミット履歴が変更される
基本的な構文は以下の通りです。
bashgit reset [オプション] [コミット指定]
主なコミット指定方法
指定方法 | 意味 |
---|---|
HEAD~1 | 1 つ前のコミット |
HEAD~2 | 2 つ前のコミット |
abc123 | 特定のコミットハッシュ |
main | main ブランチの最新コミット |
課題
git reset を間違えて使うとどうなるか
git reset
を誤って使用すると、以下のような深刻な問題が発生する可能性があります。
作業内容の完全消失
最も危険なのは --hard
オプションの誤用です。未保存の変更がすべて失われてしまいます。
bash# 危険な例:作業中の変更がすべて消える
git reset --hard HEAD~3
Error: fatal: HEAD~3: cannot resolve revision
存在しないコミットを指定した場合のエラーです。
復旧困難な状況 一度実行してしまうと、元の状態に戻すのが非常に困難になるケースがあります。
bash# 間違った例:重要なコミットを削除
git reset --hard abc123 # abc123が存在しない場合
チーム開発での影響 既にプッシュ済みのコミットをリセットすると、他のメンバーとの履歴に齟齬が生じます。
各オプションの違いがわからない問題
多くの開発者が混乱する理由は、3 つのオプションの動作範囲の違いが直感的でないことです。
以下の表で、各オプションの影響範囲を比較します。
オプション | コミット履歴 | ステージングエリア | ワーキングディレクトリ |
---|---|---|---|
--soft | リセット | 保持 | 保持 |
--mixed | リセット | リセット | 保持 |
--hard | リセット | リセット | リセット |
よくある勘違い
bash# 勘違い例1:--softでファイルの変更も戻ると思い込む
git reset --soft HEAD~1
# 実際:コミットのみリセット、ファイルの変更は残る
# 勘違い例2:--mixedで作業ディレクトリも変わると思い込む
git reset --mixed HEAD~1
# 実際:ステージングエリアのみリセット、ファイルの変更は残る
データ損失の危険性
Git は基本的にデータを失わないように設計されていますが、git reset --hard
は例外的にデータを完全に削除する可能性があります。
回復不可能なケース
bash# 未コミットの変更がある状態で実行
echo "重要な変更" > important.txt
git reset --hard HEAD~1 # important.txtの変更が失われる
Error: error: Your local changes to the following files would be overwritten
このエラーは Git が親切に出してくれる警告です。無視してはいけません。
安全な回復方法の限界
git reflog
で履歴を確認できますが、ワーキングディレクトリの変更は記録されません。
bash# reflogで確認(コミットのみ)
git reflog
# ab1234c HEAD@{0}: reset: moving to HEAD~1
# def5678 HEAD@{1}: commit: 重要な機能追加
解決策
git reset --soft の使い方
--soft
オプションは最も安全なリセット方法です。コミット履歴のみを変更し、ステージングエリアとワーキングディレクトリの内容は保持されます。
基本的な使用方法
bash# 直前のコミットを取り消す
git reset --soft HEAD~1
実行後の状態確認をしてみましょう。
bash# 現在の状態を確認
git status
# On branch main
# Changes to be committed:
# modified: example.js
# new file: feature.js
この例では、コミットは取り消されましたが、変更内容はステージングエリアに残っています。そのため、すぐに新しいコミットメッセージで再コミットできます。
コミットメッセージの修正に最適
bash# 元のコミット
git commit -m "typo fix"
# より適切なメッセージで再コミット
git reset --soft HEAD~1
git commit -m "ユーザー入力バリデーション機能のtypo修正"
複数のコミットをまとめる場合
bash# 3つのコミットを1つにまとめる
git reset --soft HEAD~3
git commit -m "ユーザー認証機能の実装"
git reset --mixed の使い方
--mixed
はデフォルトオプションで、コミット履歴とステージングエリアをリセットしますが、ワーキングディレクトリの内容は保持します。
基本構文
bash# 以下は同じ意味
git reset HEAD~1
git reset --mixed HEAD~1
ステージングエリアのリセット用途
間違ってステージングエリアに追加してしまったファイルを取り消したい場合に便利です。
bash# 誤って全ファイルを追加
git add .
# 特定のファイルのステージングを取り消し
git reset HEAD sensitive-config.txt
実行後の確認をしてみます。
bashgit status
# On branch main
# Changes not staged for commit:
# modified: example.js
# modified: feature.js
# Untracked files:
# sensitive-config.txt
段階的なコミット作成 大きな変更を複数の小さなコミットに分割したい場合に活用できます。
bash# 複数ファイルの変更を含むコミットをリセット
git reset --mixed HEAD~1
# 段階的に再コミット
git add feature-auth.js
git commit -m "認証機能の追加"
git add feature-validation.js
git commit -m "バリデーション機能の追加"
git reset --hard の使い方
--hard
オプションは最も強力で、同時に最も危険な方法です。コミット履歴、ステージングエリア、ワーキングディレクトリのすべてを指定したコミットの状態に戻します。
基本的な使用方法
bash# すべてを指定コミットの状態に戻す
git reset --hard HEAD~1
使用前の安全確認
bash# 現在の変更を確認
git status
git diff
# 重要な変更がある場合は一時保存
git stash push -m "作業中の変更を一時保存"
完全なやり直しが必要な場合
実装を根本的に変更したい場合や、実験的な変更を完全に破棄したい場合に使用します。
bash# 実験的なブランチで試行錯誤後
git log --oneline
# abc123 実験的な機能C
# def456 実験的な機能B
# ghi789 実験的な機能A
# jkl012 安定版
# 安定版に完全に戻す
git reset --hard jkl012
リモートブランチとの同期
bash# リモートの最新状態に完全に合わせる
git fetch origin
git reset --hard origin/main
安全にリセットする方法
Git リセットを安全に実行するための手順をご紹介します。
事前バックアップの作成
bash# 現在の状態でブランチを作成(バックアップ)
git branch backup-$(date +%Y%m%d-%H%M%S)
# または現在のコミットハッシュをメモ
git rev-parse HEAD
# 出力例:abc123def456...
段階的な確認手順
- 現在の状態を詳細に確認
- バックアップの作成
- リセットの実行
- 結果の検証
bash# 1. 現在の状態確認
git status
git log --oneline -5
# 2. バックアップ作成
git branch backup-before-reset
# 3. リセット実行(例:soft)
git reset --soft HEAD~1
# 4. 結果検証
git status
git log --oneline -5
回復方法の準備
万が一の際の回復手順も把握しておきましょう。
bash# reflogで操作履歴を確認
git reflog
# abc123 HEAD@{0}: reset: moving to HEAD~1
# def456 HEAD@{1}: commit: 重要な機能
# 特定の状態に戻す
git reset --hard HEAD@{1}
具体例
ケース 1:コミットメッセージを修正したい場合
開発中によくある「コミットメッセージをもっとわかりやすくしたい」というケースです。
状況設定 ユーザー認証機能を実装して、以下のようにコミットしたとします。
bashgit add auth.js
git commit -m "fix" # わかりにくいメッセージ
解決手順
以下の図は、コミットメッセージ修正の流れを示しています。
mermaidsequenceDiagram
participant W as ワーキングディレクトリ
participant S as ステージングエリア
participant R as リポジトリ
Note over R: コミット: "fix"
R->>S: git reset --soft HEAD~1
Note over S: 変更内容が戻る
S->>R: git commit -m "適切なメッセージ"
Note over R: コミット: "ユーザー認証機能のバグ修正"
実際のコマンド操作は以下の通りです。
bash# 1. 現在の状態確認
git log --oneline -3
# abc123 fix
# def456 ユーザー登録機能の追加
# ghi789 初期設定
# 2. ソフトリセットでコミットのみ取り消し
git reset --soft HEAD~1
# 3. 状態確認(変更内容はステージングエリアに残る)
git status
# On branch main
# Changes to be committed:
# modified: auth.js
# 4. 適切なメッセージで再コミット
git commit -m "ユーザー認証機能のセッション管理バグ修正"
確認結果
bashgit log --oneline -3
# bcd234 ユーザー認証機能のセッション管理バグ修正
# def456 ユーザー登録機能の追加
# ghi789 初期設定
ケース 2:ステージングエリアをリセットしたい場合
間違ったファイルをステージングエリアに追加してしまった場合の対処法です。
状況設定 プロジェクトファイルを整理中に、機密情報を含む設定ファイルも一緒にステージングしてしまいました。
bash# 作業ファイルを編集
echo "新機能の実装" > feature.js
echo "SECRET_KEY=12345" > .env # 機密情報
# 誤って全ファイルを追加
git add .
解決手順
bash# 1. 現在のステージング状況確認
git status
# On branch main
# Changes to be committed:
# new file: feature.js
# new file: .env
# 2. 機密ファイルのみステージングから削除
git reset HEAD .env
# 3. 確認
git status
# On branch main
# Changes to be committed:
# new file: feature.js
# Untracked files:
# .env
より安全な方法
.gitignore
ファイルで事前に除外設定をしておきます。
bash# .gitignoreファイルに追加
echo ".env" >> .gitignore
echo "*.log" >> .gitignore
echo "node_modules/" >> .gitignore
# .gitignoreをコミット
git add .gitignore
git commit -m ".gitignoreファイルの追加"
ケース 3:作業ディレクトリごと元に戻したい場合
実験的な変更を完全に破棄して、安定した状態に戻したいケースです。
状況設定 新しいライブラリを試していたところ、プロジェクトが不安定になってしまいました。
bash# 実験的な変更を複数実施
git log --oneline -5
# abc123 ライブラリBの試行錯誤
# def456 ライブラリAの実験
# ghi789 設定ファイル変更
# jkl012 安定版(ここに戻したい)
# mno345 前回の機能追加
解決手順
bash# 1. 作業内容を一時保存(必要に応じて)
git stash push -m "実験中の変更を一時保存"
# 2. 安全なコミットまで完全にリセット
git reset --hard jkl012
# 3. 状態確認
git log --oneline -3
# jkl012 安定版
# mno345 前回の機能追加
# pqr678 その他の機能
git status
# On branch main
# nothing to commit, working tree clean
代替手段:新しいブランチでの再開
bash# 別のアプローチ:新しいブランチを作成
git checkout -b feature-new-library jkl012
# 実験を継続する場合の安全な方法
ケース 4:複数コミットを取り消したい場合
機能実装を段階的に進めていたが、設計を見直すことになったケースです。
状況設定 ユーザー管理機能を 3 段階で実装していましたが、要件変更により全体を作り直すことになりました。
bashgit log --oneline -6
# abc123 ユーザー削除機能
# def456 ユーザー編集機能
# ghi789 ユーザー表示機能
# jkl012 基盤となるコミット(ここまで戻す)
# mno345 その他の機能
# pqr678 初期コミット
解決手順
複数コミットのリセットを図で説明します。
mermaidflowchart LR
subgraph before[リセット前]
b1[基盤コミット] --> b2[表示機能] --> b3[編集機能] --> b4[削除機能 HEAD]
end
subgraph after[リセット後]
a1[基盤コミット HEAD]
a2[未コミット: 表示機能コード]
a3[未コミット: 編集機能コード]
a4[未コミット: 削除機能コード]
end
before --> after
style b4 fill:#ffcccc
style a1 fill:#ccffcc
図で理解できる要点:
- 3 つのコミットが取り消される
- コードの変更内容は保持される(--soft の場合)
- 基盤コミットから再スタートできる
bash# 1. バックアップブランチ作成
git branch backup-user-management
# 2. 基盤コミットまでソフトリセット
git reset --soft jkl012
# 3. 状態確認
git status
# On branch main
# Changes to be committed:
# new file: user-display.js
# new file: user-edit.js
# new file: user-delete.js
git log --oneline -3
# jkl012 基盤となるコミット
# mno345 その他の機能
# pqr678 初期コミット
新しい設計でのコミット
bash# 新しい設計に基づいて再実装
git reset HEAD # ステージングエリアもクリア
rm user-*.js # 古い実装ファイルを削除
# 新しい設計で実装
echo "新しいユーザー管理クラス" > UserManager.js
git add UserManager.js
git commit -m "新設計によるユーザー管理機能の基盤実装"
まとめ
git reset の使い分けチートシート
適切な git reset
オプションを素早く選択できるよう、チートシートをまとめました。
シチュエーション | 使用オプション | コマンド例 | 注意点 |
---|---|---|---|
コミットメッセージ修正 | --soft | git reset --soft HEAD~1 | 最も安全 |
ステージング取り消し | --mixed | git reset HEAD file.txt | デフォルト |
完全なやり直し | --hard | git reset --hard HEAD~2 | 危険 |
複数コミットの統合 | --soft | git reset --soft HEAD~3 | 再コミット必要 |
実験的変更の破棄 | --hard | git reset --hard origin/main | バックアップ推奨 |
緊急時の判断フロー
mermaidflowchart TD
start([git reset が必要]) --> q1{コードの変更を保持したい?}
q1 -->|はい| q2{ステージングエリアも保持したい?}
q1 -->|いいえ| hard[git reset --hard]
q2 -->|はい| soft[git reset --soft]
q2 -->|いいえ| mixed[git reset --mixed]
soft --> safe1[最も安全]
mixed --> safe2[比較的安全]
hard --> danger[注意が必要]
style soft fill:#ccffcc
style mixed fill:#ffffcc
style hard fill:#ffcccc
覚えておきたいポイント
1. 安全性の順序
--soft
> --mixed
> --hard
の順で安全です。迷ったときは --soft
から試しましょう。
2. バックアップの重要性
bash# 必ず実行前にバックアップ
git branch backup-$(date +%Y%m%d-%H%M%S)
3. reflog での復旧
bash# 操作履歴の確認
git reflog
# 特定の状態への復旧
git reset --hard HEAD@{2}
4. チーム開発での注意
プッシュ済みのコミットは原則としてリセットしないこと。代わりに git revert
を検討してください。
bash# 安全な取り消し方法(プッシュ済みの場合)
git revert HEAD~1
5. 作業フローでの活用
- 開発中:
--soft
でコミット整理 - 実験時:
--hard
で完全リセット - ステージング管理:
--mixed
で細かい調整
関連リンク
- article
git reset の使い分け完全ガイド:soft・mixed・hard の違いを理解する
- article
Git で特定のコミットを打ち消す!git revert の正しい使い方
- article
Cline で Git 操作を自動化する方法
- article
【トラブル解決】git push が拒否される原因と安全な対応手順
- article
Cursor × GitHub 連携:プルリク作成からレビューまで自動化する方法
- article
Git の fetch と pull の違いを理解してトラブルを回避する方法
- article
SolidJS のリアクティブ思考法:signal と effect を“脳内デバッグ”で理解
- article
git reset の使い分け完全ガイド:soft・mixed・hard の違いを理解する
- article
Python 3.13 新機能総まとめ:Faster CPython と型システムの進化を一望
- article
Gemini CLI のアーキテクチャを図解で理解:入力 → 推論 → 出力のデータフロー全貌
- article
Pinia アーキテクチャ超図解:リアクティビティとストアの舞台裏を一枚で理解
- article
FFmpeg アーキテクチャ超図解:demuxer→decoder→filter→encoder→muxer の流れを一望
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来