「作業内容がすべて消えた」と気づいた時の絶望感
git reset --hard コマンドを実行した瞬間、5時間分のコーディング成果が消え去ったことに気づき、心臓がバクバクし、冷や汗が止まらなくなる。これは、ほとんどのエンジニアが少なくとも一度は経験する状況です。あるいは、マージ済みだと思い込んで自信満々にブランチを削除したものの、実は大きな間違いだったと後で気づくこともあるでしょう。
そんな時、普段使っている git log コマンドは役に立ちません。それらのコミットは、ブランチの表示履歴から消えてしまっているからです。しかし、最初からコードを書き直す必要はありません。Gitには「Git reflog」という、非常に強力な隠れたログ記録メカニズムが備わっています。
なぜ git log ではダメで、git reflog なら可能なのか?
この2つのツールを効果的に使い分けるために、違いを明確に理解しておきましょう:
- git log: ブランチのコミット履歴を表示します。リセットしたりブランチを削除したりすると、関連するコミットは表示されなくなります。
- git reflog: “reference logs” の略です。
HEADポインタが位置を変えるたびに、その履歴をすべて記録します。コミット、チェックアウト、リセット、マージなど、Gitはローカルで密かにその足跡を保存しています。
本質的に、Gitはリセットしてもすぐにデータを削除するわけではありません。単に参照(reference)を外すだけです。データは、ガベージコレクタ(Garbage Collector)が実行されるまでデータベース内に残ります。デフォルトでは、Gitはこれらの「孤立した」データを30日から90日間保持します。
Reflogのログ行を読み解く
HEADを変更する操作を行うたびに、reflogに新しい行が追加されます。以下の例を見てみましょう:
e1a2b3c HEAD@{0}: commit: ショッピングカートのロジック修正
d4e5f6g HEAD@{1}: checkout: moving from feature-abc to main
7h8i9j0 HEAD@{2}: reset: moving to HEAD~1
この構造は主に3つの部分で構成されています。最初はコミットの短縮ハッシュ。次に HEAD@{n} で、現在の状態から何ステップ前かを示します。最後は実行したアクションの説明です。
実際に役立つ2つの救出シナリオ
チームメンバーが誤って「ポチッ」としてしまった時に、私がよく使う対処法を紹介します。
1. git reset –hard 実行後の復元
コミットCにいたのに、誤ってコミットAにリセットしてしまったとしましょう。BとCの全コードが git log から消えてしまいます。
ステップ1: git reflog コマンドでログを確認します。リセットコマンドを実行する直前の最後のコミットの説明を探してください。
ステップ2: プロジェクトをその状態に戻します。すべてのコードを完全に取り戻したい場合は、次のコマンドを使用します:
git reset --hard e1a2b3c # e1a2b3cを見つけたハッシュ値に置き換えてください
もし、コードだけを取り戻し、現在編集中のファイルの状態は維持したい場合は、--hard の代わりに --soft を使用してください。
2. 誤って削除したブランチを見つける
サーバーにプッシュ済みだと思い込んで、開発者が feature-payment ブランチを削除してしまったケースに遭遇したことがあります。実際には、最新েরコードはローカルマシンにしかありませんでした。この時、git branch ではそのブランチ名は表示されません。
対処法は非常にシンプルです。git reflog と入力し、削除される前のそのブランチの最後のコミットを探します。その後、そのハッシュ値からブランチを再作成します:
git branch feature-payment 7h8i9j0
たった一行のコマンドで、ブランチの全コミット履歴が、まるで何事もなかったかのように復活します。
使用時の3つの重要な注意点
非常に強力な git reflog ですが、万能の魔法ではありません。以下の3つのルールを覚えておいてください:
- 自分のローカルマシンでのみ有効: Reflogはローカルのログであり、GitHubやGitLabにはプッシュされません。自分のマシンで削除したコードを、同僚のマシンから復元することはできません。
- コミット済みのものだけが救える:
git addやコミットを一度もしていない状態でgit checkout .などを行ってしまった場合、reflogにデータは残りません。下書きレベルでも、こまめにコミットする習慣をつけましょう。 - 保存期間には限りがある: Gitは、90日後(アクセス可能なコミットの場合)または30日後(孤立したコミットの場合)にreflogをクリーンアップします。古いコードが必要になったら、あまり時間を置かずに探し始めましょう。
おわりに
git reflog をソースコードの「ブラックボックス(飛行記録装置)」のように考えてください。その仕組みを理解しておけば、複雑なGit操作も自信を持って行えるようになります。次回、誤って削除してしまった時は、パニックになる前に落ち着いて git reflog と入力してみましょう!
