T-CREATOR

Git でやらかしても大丈夫!git reflog で履歴をたどって、あらゆるミスから復旧

Git でやらかしても大丈夫!git reflog で履歴をたどって、あらゆるミスから復旧

突然の「あっ!やばい!」という感覚、Git を使っている方なら一度は経験したことがあるのではないでしょうか。コミットを間違えて消してしまった、大事なブランチを削除してしまった、あるいはgit reset --hardを実行した後に「やっぱり元に戻したい」と思った瞬間...。

そんなときに救世主となるのが、今回ご紹介するgit reflogコマンドです。このコマンドを知っておくだけで、多くの Git トラブルから脱出できるようになります。

Git reflog とは何か:基本概念と仕組みの解説

git reflog(Reference Log)は、ローカルリポジトリでの HEAD の移動履歴を記録する Git の機能です。簡単に言えば、あなたの Git リポジトリで行ったほぼすべての操作(コミット、チェックアウト、リセット、マージなど)の履歴を保持しています。

通常のgit logがコミット履歴のみを表示するのに対し、reflogは HEAD の移動すべてを記録します。これには、resetrebaseなどの「歴史を書き換える」操作も含まれます。つまり、公式の歴史書に載らない裏の出来事まで記録しているわけです。

reflog が記録する主な情報:

  • コミットの作成
  • ブランチの切り替え
  • リセット操作
  • マージ操作
  • リベース操作
  • チェリーピック操作

reflog の仕組みは非常にシンプルです。Git は.git​/​logs​/​ディレクトリにログファイルを保持し、すべての参照の更新履歴を記録しています。

よくある Git のやらかしパターン

Git を使っていると、様々な「やらかし」が起こりがちです。以下に代表的なものを紹介します。

誤ったコミットの削除

ruby$ git commit -m "重要な機能を実装"
$ git reset --hard HEAD~1  # 「やっぱりやめよう」と思ってリセット
$ ...「あっ、やっぱり必要だった!」

このように、一度コミットしたものを削除してから「やっぱり必要だった」と気づくことはよくあります。

間違ったブランチへのコミット

ruby$ git checkout master  # 本当はfeature/newブランチで作業するつもりだった
$ ... (作業) ...
$ git commit -m "新機能の実装"
$ ...「あっ、masterブランチでコミットしてしまった!」

特に複数のブランチを行き来している場合、意図しないブランチでコミットしてしまうことがあります。

誤った rebase 操作

ruby$ git checkout feature
$ git rebase master  # コンフリクトが多発
$ ... (複雑な修正作業) ...
$ ...「あっ、やっぱりrebaseはやめたい!」

複雑な rebase 操作を行った後に「元に戻したい」と思うことは少なくありません。

不用意な reset --hard

ruby$ git reset --hard HEAD~3  # 最近の3つのコミットを削除
$ ...「あっ、必要なコミットまで消してしまった!」

reset --hardは強力な反面、取り返しがつかないと思われがちなコマンドです。

git reflog の基本的な使い方:コマンド解説と読み方

まずは基本的な使い方から見ていきましょう。

ruby$ git reflog

このコマンドを実行すると、以下のような出力が得られます:

kotlin1a2b3c4 (HEAD -> master) HEAD@{0}: commit: 最新のコミットメッセージ
5d6e7f8 HEAD@{1}: commit: 一つ前のコミットメッセージ
9g0h1i2 HEAD@{2}: checkout: moving from feature to master
3j4k5l6 HEAD@{3}: commit: featureブランチでのコミット
...

出力の読み方:

  • 1a2b3c4 はコミットハッシュ
  • HEAD@{0} は操作の順番(0 が最新)
  • commit:checkout: などは操作の種類
  • 最後にメッセージや詳細が表示されます

特定の時間枠での操作を見たい場合は:

ini$ git reflog show --since="1 hour ago"
$ git reflog show --until="yesterday"

また、特定のブランチの reflog を見るには:

ruby$ git reflog show master

実践:具体的な復旧シナリオと手順

それでは、先ほど紹介した「やらかし」パターンごとに、reflog を使った復旧方法を見ていきましょう。

シナリオ 1:誤ったコミットの削除からの復活

perl$ git reset --hard HEAD~1  # 誤ってコミットを削除
$ git reflog  # 操作履歴を確認
7f8g9h0 HEAD@{0}: reset: moving to HEAD~1
1a2b3c4 HEAD@{1}: commit: 重要な機能を実装  # これが削除したコミット
...
$ git reset --hard 1a2b3c4  # 削除したコミットに戻る

このように、削除したコミットのハッシュが分かれば、そこに戻ることができます。

シナリオ 2:間違ったブランチへのコミット修正

shell$ git reflog  # 操作履歴を確認
1a2b3c4 HEAD@{0}: commit: 新機能の実装  # masterに誤ってコミットしたもの
5d6e7f8 HEAD@{1}: checkout: moving from feature/new to master
...
$ git branch feature/new 1a2b3c4  # 誤ったコミットを指す新ブランチを作成
$ git reset --hard 5d6e7f8  # masterを元に戻す
$ git checkout feature/new  # 新ブランチに切り替え

シナリオ 3:誤った rebase 操作からの復帰

perl$ git reflog  # 操作履歴を確認
1a2b3c4 HEAD@{0}: rebase finished: returning to refs/heads/feature
...
9g0h1i2 HEAD@{10}: checkout: moving from master to feature  # rebase前の状態
...
$ git reset --hard 9g0h1i2  # rebase前の状態に戻る

シナリオ 4:不用意な reset --hard からの復活

perl$ git reflog  # 操作履歴を確認
1a2b3c4 HEAD@{0}: reset: moving to HEAD~3  # ここでreset --hardを実行
5d6e7f8 HEAD@{1}: commit: 必要な機能3
9g0h1i2 HEAD@{2}: commit: 必要な機能2
3j4k5l6 HEAD@{3}: commit: 必要な機能1
...
$ git reset --hard 3j4k5l6  # 消してしまった一番古いコミットに戻る

reflog と併用すると便利な Git コマンド

reflog と組み合わせることで、さらに強力になるコマンドをいくつか紹介します。

git cherry-pick

特定のコミットだけを取り出したい場合に便利です。

perl$ git reflog
1a2b3c4 HEAD@{0}: reset: moving to HEAD~3
5d6e7f8 HEAD@{1}: commit: 必要な機能3  # このコミットだけ必要
...
$ git cherry-pick 5d6e7f8  # 必要なコミットだけを適用

git fsck

削除されたオブジェクトを発見するのに役立ちます。

python-repl$ git fsck --lost-found
dangling commit 1a2b3c4...  # どのブランチからも参照されていないコミット
...

git show

特定のコミットの内容を確認するのに使います。

ruby$ git reflog
1a2b3c4 HEAD@{0}: commit: 何かのコミット
...
$ git show 1a2b3c4  # コミットの詳細を確認

事前の備え:reflog を活用するための環境設定

reflog をより効果的に活用するための設定をいくつか紹介します。

reflog の保持期間を延長する

デフォルトでは、reflog のエントリは 90 日間保持されます。これを延長するには:

arduino$ git config --global gc.reflogExpire "1 year"

より詳細な reflog を記録する

arduino$ git config --global core.logAllRefUpdates true

これにより、すべての参照の更新が記録されるようになります。

reflog のバックアップ

重要なプロジェクトでは、定期的に.git​/​logs​/​ディレクトリをバックアップしておくと安心です。

shell$ cp -r .git/logs/ ~/backup/git-logs-$(date +%Y%m%d)/

まとめ

git reflogは、Git での「やらかし」からあなたを救う強力なツールです。

  • reflog はリポジトリでのすべての HEAD の移動を記録している
  • コミットの削除、間違ったブランチ操作、reset --hard など、多くのミスから復旧可能
  • 基本的な使い方を覚えておくだけで、多くの Git トラブルを解決できる
  • 適切な設定をしておくことで、より長期間、より詳細な履歴を保持できる

Git は非常に強力なツールですが、時に「取り返しがつかない」と感じる場面もあります。しかし、git reflogを知っていれば、多くの場合は元の状態に戻すことができます。ぜひ、日常の Git 操作にreflogを取り入れて、より安心してバージョン管理を行ってください。

関連リンク