reflogの基本
git reflog
git reflog <ブランチ名>
git reflog show <参照>
# HEADの移動履歴を表示
git reflog
# 出力例:
# a1b2c3d (HEAD -> main) HEAD@{0}: commit: 新機能追加
# e4f5g6h HEAD@{1}: reset: moving to HEAD~1
# i7j8k9l HEAD@{2}: commit: バグ修正
# m1n2o3p HEAD@{3}: checkout: moving from feature to main
各行の構成はこのとおりです。ハッシュ値はそのときのコミット、参照はHEAD@{n}形式の履歴番号、操作は実行されたGitコマンドを表します。
削除したコミットの復元
# 現在の状況
git log --oneline
# abc1234 最新コミット
# def5678 前のコミット
# 誤ってリセット実行
git reset --hard HEAD~2
# コミットが消失
git log --oneline
# hij9012 さらに古いコミット
# reflogで履歴確認
git reflog
# hij9012 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~2
# abc1234 HEAD@{1}: commit: 最新コミット
# def5678 HEAD@{2}: commit: 前のコミット
# 消失したコミットを復元
git reset --hard HEAD@{1}
削除したブランチの復元
# ブランチ作成と作業
git checkout -b feature/api-endpoint
git add src/api.js
git commit -m "API エンドポイント実装"
# メインブランチに戻ってブランチ削除
git checkout main
git branch -D feature/api-endpoint
# ブランチを復元したい場合
git reflog
# a1b2c3d (HEAD -> main) HEAD@{0}: checkout: moving from feature/api-endpoint to main
# e4f5g6h HEAD@{1}: commit: API エンドポイント実装
# ブランチを復元
git checkout -b feature/api-endpoint e4f5g6h
リファクタリング失敗からの復旧
# リファクタリング作業開始
git checkout -b refactor/code-cleanup
# 複数ファイルの変更作業
git add src/**/*.js
git commit -m "関数名変更開始"
git add src/utils/
git commit -m "ユーティリティ関数整理"
git add package.json
git commit -m "依存関係更新"
# 問題発生、以前の状態に戻したい
git reflog show refactor/code-cleanup
# abc1234 (HEAD -> refactor/code-cleanup) HEAD@{0}: commit: 依存関係更新
# def5678 HEAD@{1}: commit: ユーティリティ関数整理
# ghi9012 HEAD@{2}: commit: 関数名変更開始
# jkl3456 HEAD@{3}: checkout: moving from main to refactor/code-cleanup
# 最初の変更直後の状態に戻る
git reset --hard ghi9012
マージ失敗の復旧
# マージ前の状態記録
git checkout main
git reflog
# a1b2c3d (HEAD -> main) HEAD@{0}: checkout: moving from feature to main
# 問題のあるブランチをマージ
git merge feature/experimental
# マージ後に問題発生
git reflog
# e4f5g6h (HEAD -> main) HEAD@{0}: merge feature/experimental
# a1b2c3d HEAD@{1}: checkout: moving from feature to main
# マージ前の状態に復旧
git reset --hard HEAD@{1}
期間を指定した履歴確認
# 過去1時間の変更履歴
git reflog --since="1 hour ago"
# 昨日から今日までの履歴
git reflog --since="yesterday" --until="now"
# 特定日付の範囲
git reflog --since="2024-01-01" --until="2024-01-31"
制限事項
ISSUE - 課題
reflogの保存期間はデフォルトで90日間です。この期間を過ぎた履歴は自動的に削除されるため、古い変更は復旧できません。
# 保存期間の確認
git config gc.reflogExpire
# デフォルト: 90.days
# 保存期間の変更
git config gc.reflogExpire 120.days
# 未到達オブジェクトのreflog期限
git config gc.reflogExpireUnreachable
# デフォルト: 30.days
# 手動でガベージコレクション実行
git gc --prune=now
reflogは誤操作からの復旧において役立つものの、最終手段という印象です。
私も初学者のころは使っていましたが、今になると新鮮なコマンドに感じます。
引き出しに持っておく程度に捉えておきましょう。