- Git
git reset –hardを取り消す方法|reflogで復元する手順
git reset --hardで消してしまったコミットは、多くの場合「git reflog」で復元できます。Gitは、HEADやブランチが指していた位置の履歴を記録していて、消えたように見えるコミットも、実体はしばらくリポジトリの中に残っているからです。
ただし、一度もコミットしていない変更は、reset --hardで消えると基本的に戻りません。この記事では、まず落ち着いて確認すべきこと、状況別の復元手順、そして次から焦らないための習慣までを解説します。
まず、やってはいけないこと
復元の前に、次の操作は避けてください。消えたコミットの手がかりが減る可能性があります。
git gcやgit pruneを実行する(到達できないコミットが掃除される)- 焦って別の reset や checkout を何度も重ねる(reflogが読みにくくなる)
まず git reflog を見る。 これだけで大半の状況は解決に向かいます。
git reflogとは
reflogは、HEAD(とブランチ)がどのコミットを指していたかの記録です。コミット、reset、checkout、rebase、mergeなど、HEADが動くたびに1行ずつ追加されます。
git reflog
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
e4f5g6h HEAD@{1}: commit: ログイン画面のバリデーションを追加
i7j8k9l HEAD@{2}: commit: APIのエラーハンドリングを修正
...
HEAD@{1} は「1つ前にHEADが指していた場所」という意味です。reset直前の状態は、たいてい HEAD@{1} にあります。
reflogはローカルの記録で、既定では到達できなくなったコミットの記録は30日、それ以外は90日保持されます(gc.reflogExpireUnreachable / gc.reflogExpire)。気づいたら早めに復元するのが安全です。
状況別の復元手順
ケース1:reset --hardの直後に取り消したい
reset直後なら、ORIG_HEAD が直前の位置を覚えています。
git reset --hard ORIG_HEAD
ORIG_HEADは、reset・rebase・mergeなどの「HEADを大きく動かす操作」の直前の位置です。直後であれば、これが一番手軽です。
ケース2:少し前のresetを取り消したい
reflogで戻したい時点を探し、そこへresetします。
git reflog
# 戻したい行(例: HEAD@{3})を確認して
git reset --hard HEAD@{3}
いきなりresetするのが不安なら、まずブランチを作って保護するのがおすすめです。
git branch rescue HEAD@{3}
git log rescue # 中身を確認してから
ブランチとして残しておけば、その後どう操作しても消えません。
ケース3:削除したブランチを復元したい
git reflog
# 削除したブランチの最後のコミットを探す(checkoutやcommitの記録から)
git branch 復元するブランチ名 <コミットのハッシュ>
git branch -D の直後であれば、削除時のメッセージに「Deleted branch xxx (was 1a2b3c4).」とハッシュが表示されているので、それをそのまま使えます。
ケース4:rebaseを取り消したい
rebase直後なら ORIG_HEAD にrebase前の位置が残っています。
git reset --hard ORIG_HEAD
時間が経っている場合は、reflogで rebase (start) の直前の行を探し、その位置へ戻します。
git reflog
# 「rebase (start)」より1つ下(古い側)の行が、rebase前の状態
git reset --hard HEAD@{n}
ケース5:消したstashを復元したい
git stash drop や git stash clear で消したstashは、reflogには残りませんが、到達できないコミットとして残っていることがあります。
git fsck --unreachable | grep commit
# 表示されたハッシュを1つずつ確認
git show <ハッシュ>
# 目的のものが見つかったら
git stash apply <ハッシュ>
stashを消した直後なら、ターミナルに表示された「Dropped refs/stash@{0} (ハッシュ)」のハッシュでそのまま git stash apply できます。
push済みの場合は「reset」ではなく「revert」
すでにリモートにpushしたコミットを取り消したい場合、resetして強制pushするのは避けるのが原則です。他のメンバーが取り込んだ履歴と食い違い、チームの作業を壊してしまうことがあります。
git revert <取り消したいコミット>
revertは、「打ち消すコミット」を新しく追加するので、履歴を書き換えずに変更を取り消せます。共有ブランチでは、これが安全な方法です。
どうしても強制pushが必要な場合は、--force ではなく --force-with-lease を使います。自分が最後に確認した後に誰かがpushしていたら失敗してくれるので、他人の作業を上書きする事故を防げます。
復元できないケース
- 一度もコミットもステージもしていない変更 — reset --hardで消えた作業ツリーの変更は、Gitの記録に残っていないため復元できません。エディタのローカル履歴機能(IDEの履歴)が最後の頼みです
- ステージ(git add)だけした変更 — コミットはしていなくても、
git fsck --lost-foundでファイルの中身(blob)が見つかる場合があります - reflogの保持期間が過ぎ、gcで掃除された後 — 時間が経つほど復元は難しくなります
reset --soft / --mixed / --hardの違い
そもそもの理解として、resetには3つのモードがあります。
| オプション | HEAD(履歴) | ステージ | 作業ツリー(ファイル) |
|---|---|---|---|
--soft |
戻る | そのまま | そのまま |
--mixed(既定) |
戻る | 戻る | そのまま |
--hard |
戻る | 戻る | 戻る(変更が消える) |
「コミットをやり直したいだけ」なら、--soft や --mixed で十分なことがほとんどです。作業ツリーの変更まで消すのは --hard だけなので、使う前に一度立ち止まる習慣が事故を減らします。
次から焦らないための習慣
- 危険な操作の前にブランチを1本作る —
git branch backup-before-rebaseの1行で、どう失敗しても戻れます - 作業途中でもこまめにコミットする — コミットさえしていれば、reflogで取り戻せます
- --hardより先に git status と git stash — 消していいか迷う変更は、stashに退避してから操作する
- 強制pushは --force-with-lease を習慣に
よくある質問
Q. reflogは他の人のリポジトリでも見られますか? A. 見られません。reflogはローカルの記録なので、自分のクローンにしかありません。他の人が消したコミットは、その人の環境のreflogで復元してもらう必要があります。
Q. reset --hardで消したファイルの変更(未コミット)は本当に戻りませんか?
A. Gitの機能では戻りません。ステージ済みなら git fsck --lost-found で中身が見つかる場合があります。エディタやIDEのローカル履歴も確認してください。
Q. resetとrevertはどう使い分けますか? A. 自分のローカルだけにあるコミットならreset、共有ブランチにpush済みのコミットならrevertです。
Q. reflogはいつまで残りますか? A. 既定では、到達できなくなったコミットの記録は30日、それ以外は90日です。設定で変更できますが、気づいたら早めに復元してください。
まとめ
- reset --hardで消えたコミットは、まず git reflog。直後なら
git reset --hard ORIG_HEAD - 不安なら、復元先に ブランチを作って保護してから確認する
- 削除したブランチ・rebase・stashも、reflogやfsckで多くの場合復元できる
- push済みなら revert、強制pushは --force-with-lease
- 未コミットの変更だけは戻らない。こまめなコミットが最大の保険
Gitは、コミットしたものを簡単には手放さない道具です。仕組みを知っておくと、rebaseもresetも怖くなくなります。株式会社RJCでは、こうした日々の開発の知識をチームで共有しながら、保険・金融・決済などのシステム開発に携わっています。
▶ RJC丸わかり https://www.r-jc.jp/guide/?mediacode=02-00001-003
▶ エントリーはこちら(1〜2分で完了します) https://www.r-jc.jp/recruitment/?mediacode=02-00001-003
株式会社RJC ― SI事業・SES事業・AI駆動開発。未経験からエンジニアに育てるのが得意な会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。