開発していると、「今の変更を全部なかったことにして、最初からやり直したい」という場面があります。
そんなときに使うのが、
git reset --hard と git clean です。
# 今の変更を別ブランチに退避
git checkout -b backup-branch
git add .
git commit -m "作業中の変更を退避"
# main に戻ってクリーンな状態に
git checkout main
git reset --hard
git clean -fd
Code language: PHP (php)
ただ、これらのコマンドは破壊的で、実行すると元に戻せません。
だからこそ、何が起きるのかを正確に理解しておく必要があります。
1. Git の基本:HEAD とブランチの仕組み
コマンドの説明に入る前に、Git の基本的な仕組みを整理しておきます。
1.1. コミットは履歴のスナップショット
Git のコミット(commit)は、プロジェクトのある時点での状態を記録したスナップショットです。
各コミットには一意の ID(ハッシュ値)が割り当てられ、親コミットへの参照を持っています。
履歴は鎖のようにつながっているイメージです。
[コミット A] ← [コミット B] ← [コミット C]
Code language: CSS (css)
1.2. ブランチはコミットを指すポインタ
ブランチ(branch)の実体は、特定のコミットを指すポインタです。main ブランチも feature ブランチも、どれも「このコミットが最新ですよ」という情報を持っているだけです。
main → [コミット C]
feature → [コミット D]
Code language: CSS (css)
新しいコミットを作ると、現在いるブランチが新しいコミットを指すように自動的に移動します。
1.3. HEAD は「今ここにいる」を示す
HEAD は、今自分がどこで作業しているかを示すポインタです。
通常は特定のブランチを指しています。
HEAD → main → [コミット C]
↑
今ここで作業中
Code language: CSS (css)
HEAD が main を指していて、main がコミット C を指している。
つまり、コミット C の状態で作業している、ということです。
1.4. 作業ディレクトリの 3 つの状態
ファイルを編集してから Git に記録するまでには、3 つの段階があります。
- 作業ディレクトリ:ファイルを直接編集している状態
- ステージングエリア:
git addでコミット準備をした状態 - リポジトリ:
git commitで履歴に記録された状態
[ファイル編集] → [git add] → [git commit]
Code language: CSS (css)
2. 変更を破棄する 2 つのコマンド
ここからが本題です。
変更を完全に破棄するには、2 つのコマンドを組み合わせます。
2.1. git reset –hard:追跡済みファイルの変更を破棄
git reset --hard は、
HEAD が指すコミットの状態に作業ディレクトリを強制的に合わせます1。
何が起きるか
- ステージング済みの変更が失われる
- 編集中のファイルの変更が失われる
- ファイル自体は削除されない(変更が元に戻るだけ)
- コミット済みの内容には影響しない
実行前と実行後を比較すると、こうなります。
実行前:
HEAD → main → [コミット C]
作業ディレクトリ: コミット C の内容 + 編集内容
実行後:
HEAD → main → [コミット C]
作業ディレクトリ: <strong>コミット C の内容</strong>(編集内容は消える)
Code language: HTML, XML (xml)
2.2. git clean -fd:未追跡ファイルを削除
git clean -fd は、
Git で追跡されていないファイルとディレクトリを削除します2。
オプションの意味は
-f:強制実行(force)。
安全装置として、このオプションなしでは実行できない-d:ディレクトリも削除対象にする(directory)
何が起きるか
- 新規作成したファイル(未追跡)が完全に削除される
- 新規作成したディレクトリ(未追跡)が完全に削除される
.gitignoreに記載されたファイルは削除されない- 追跡済みファイルには影響しない
3. 実際の使い方:仕切り直しの手順
それでは、実際に変更を破棄して main ブランチに戻る手順を見ていきます。
3.1. 現在の状態を確認する
まず、何が変更されているのか確認します。
git status
これで、変更されたファイル、新規ファイル、削除されたファイルが表示されます。念のため、残したいファイルがないか確認しておきましょう。
3.2. 追跡済みファイルの変更を破棄
git reset --hard
実行すると、編集中の変更やステージング済みの変更が全て失われます。作業ディレクトリは最新のコミットと同じ状態になります3。
3.3. 未追跡ファイルを削除
git clean -fd
これで新規作成したファイルやディレクトリが削除されます4。
3.4. クリーンな状態を確認
もう一度状態を確認します。
git status
以下のように表示されれば、完全にクリーンな状態です。
On branch main
nothing to commit, working tree clean
4. 注意点と安全な使い方
4.1. 復元不可能であることを理解する
これらのコマンドで失われた変更は、基本的に復元できません。Git の履歴にコミットされていない変更は、Git の管理外なので取り戻せないのです5。
実行前に必ず git status で確認することを習慣にしましょう。
4.2. 部分的に戻したい場合
全ての変更を破棄するのではなく、特定のファイルだけ元に戻したい場合は、別のコマンドを使います6。
# 特定ファイルの変更を破棄
git checkout -- ファイル名
# 特定ファイルをステージングから外す
git restore --staged ファイル名
Code language: PHP (php)
4.3. .gitignore のファイルは残る
git clean は .gitignore に記載されたファイルを削除しません7。
これらも削除したい場合は -x オプションを追加します。
git clean -fdx
ただし、これは依存関係(node_modules など)やビルド成果物も削除するので、実行後に再セットアップが必要になる場合があります。
5. どんな場面で使うか
私がこれらのコマンドを使うのは、主に以下のような場面です。
- テストコードを書き直したいとき
- アプローチを根本から変えたいとき
- 実験的な変更をリセットしたいとき
- マージで複雑な競合が起きて、一旦白紙に戻したいとき
逆に、「やっぱりこの変更は残しておきたいかも」と少しでも思うなら、別のブランチを作って退避させておく方が安全です。
# 今の変更を別ブランチに退避
git checkout -b backup-branch
git add .
git commit -m "作業中の変更を退避"
# main に戻ってクリーンな状態に
git checkout main
git reset --hard
git clean -fd
Code language: PHP (php)
6. まとめにかえて
git reset --hard と git clean -fd は、強力だけど危険なコマンドです。使いこなせれば開発の自由度が上がりますが、理解せずに使うとデータを失うリスクがあります。
何が起きるのかを理解し、実行前に必ず確認する。この習慣さえ身につけば、安心して使えるツールになります。
仕切り直しが必要なとき、このコマンドを思い出してください。
- 引数を省略した場合、git reset –hardはデフォルトでHEAD(現在のブランチの最新コミット)を対象とします。つまり、git reset –hard HEADと同じ動作になります。 – git resetの使い方!ステージのリセット・コミットの取り消し
- Git設定変数clean.requireForceがデフォルトのtrueに設定されているため、-f、-n、-iのいずれかのオプションが必須です。これは誤操作による重要なファイルの削除を防ぐための安全機構です。 – git clean – Gitコマンド
- この操作はローカルリポジトリのみに影響します。リモートにpush済みのコミット履歴をreset –hardで削除した場合、リモートに反映するにはgit push -fによる強制プッシュが必要ですが、チーム開発では他のメンバーに影響を与えるため避けるべきです。 – 実践 Git「ハードリセットのコマンド(強制ロールバック)」
- 実行前に必ずgit clean -fdnコマンドでドライラン(予行演習)を行い、削除対象を確認することを強く推奨します。-nオプションは実際には削除せず、何が削除されるかを表示するだけです。 – Git Cleanの使い方ガイド:未追跡ファイルを安全に削除する方法
- ただし、コミット済みの内容を誤ってgit reset –hardで戻してしまった場合は、git reflogコマンドを使って復元できます。reflogはHEADの移動履歴を記録しているため、誤った操作を取り消すことが可能です。 – git reset –hardしてしまった時に元に戻す方法
- Git 2.23以降では、git checkoutの代わりにgit restoreコマンドの使用が推奨されています。git restoreはファイル復元に特化しており、ブランチ切り替えなどの他の機能と分離されているため、誤操作のリスクが低減されます。 – Gitのrestoreを使ってファイルを元に戻そう!簡単ガイドとresetとの違い
- これはgit cleanが「Gitで追跡されていないファイル」を対象とするためで、.gitignoreに記載されたファイルは意図的に無視されているものとして扱われます。-xオプションを使用すると、これらの無視されたファイルも削除対象になります。 – Git Clean – GeeksforGeeks