Git は現在最も広く使用されているバージョン管理システムであり、さまざまな方法で変更を追跡して、コミットされた変更が失われないようにします。さらに、開発ワークフローを制御できるということは、プロジェクトの履歴がどのように見えるかを正確に判断できることを意味します。 Git には、 git commit --amend
、 git rebase
、 git reflog
reflog など、コミット履歴を書き換えるためのメカニズムがいくつかあります。
この記事では、 git reflog
を利用して、Git コミット履歴を効果的かつ簡単に再編成および書き換える方法を学びます。同時に、コミット履歴の書き換えがもたらすリスクを軽減します。
Git は、参照ログ、または単に「 reflog 」と呼ばれるシステムを使用して、ブランチのヒントの変更を追跡します。多くの場合「 ref 」と呼ばれる参照は、多くの Git コマンドがパラメーターとして受け入れるコミットまたはブランチへのポインターです。 git checkout
、 git reset
、およびgit merge
は、参照をパラメーターとして受け入れるいくつかの一般的な git コマンドの例です。
デフォルトでは、reflog は過去 90 日間の各HEAD
位置を追跡します。さらに、reflog 履歴はリポジトリ専用であり、リモートからアクセスすることはできません。ブランチ チップの reflog とは別に、 Git stash用の別の reflog があります。
reflog は、ローカル リポジトリの.git
ディレクトリの下の特定のディレクトリに保存されます。これらのgit reflog
ディレクトリは.git/logs/refs/heads/.
、 .git/logs/HEAD
、およびリポジトリでgit stash
が使用されている場合は.git/logs/refs/stash
。
基本的な reflog コマンドは次のとおりです。
# To see activity on HEAD git reflog show
上記のコマンドの出力は、次のようになります。
0a2e358 HEAD@{0}: reset: moving to HEAD~2 0254ea7 HEAD@{1}: checkout: moving from 2.2 to main c10f740 HEAD@{2}: checkout: moving from main to 2.2
その他の一般的な使用法は次のとおりです。
# To see activity on HEAD, including timestamp git reflog show --date=relative #or git reflog --relative-date # same, on some_branch git reflog show --date=relative some_branch
デフォルトでは、 git reflog
はHEAD
ref の reflog を出力します。シンボルHEAD
は、現在アクティブなブランチを示します。他の参照に使用できる reflog もあります。 git ref にアクセスするために使用される構文は、 name@{qualifier}
です。たとえば、 - otherbranch@{0}
です。 HEAD
参照に加えて、他のブランチ、タグ、リモート、および Git stash も参照できます。
すべての参照の完全な reflog を表示するには、次を実行できます。
git reflog show --all
順序付けられたインデックス以外に、各 reflog エントリにはタイムスタンプが添付されており、Git ref ポインター構文の修飾子トークンとしても利用できます。これにより、これらの reflog エントリを時間でフィルタリングできます。一般的に使用される時間修飾子の例は次のとおりです。
@{0}
@{6.minutes.ago}
@{2.hour.ago}
@{3.day.ago}
@{5.weeks.ago}
@{8.years.ago}
@{today}
@{2022-01-23.08:30:00}
@{1.day.10.hours.ago}
これらの時間修飾子は組み合わせることができます (例: 1.day.3.hours.ago
)。これらの時間修飾子の複数形も受け入れられます (例: 5.minutes.ago
)。これらは、次のようにgit reflog
コマンドと一緒に使用できます。
git reflog show develop@{3.days.ago}
git reflog
は、 show
、 expire
、 delete
などのサブコマンドと見なされる追加の引数を受け入れます。これらのサブコマンドについて詳しく説明しましょう。
前に説明したように、 show
はデフォルトで暗黙的に渡されます。 git reflog show
を実行すると、渡された引数のログが表示されます。
例えば:
git reflog develop@{0}
と同じです
git reflog show develop@{0}
さらに、 git reflog show
はgit log -g --abbrev-commit --pretty=oneline
のエイリアスです。
expire
サブコマンドは、古いまたは到達不能な reflog エントリをクリーンアップするのに役立ちます。
expire
サブコマンドは、データ損失を引き起こす可能性があります。
ただし、このサブコマンドは通常、エンド ユーザーによって使用されるのではなく、git 内部で使用されます。
「ドライラン」は、 -n
または--dry-run
オプションをgit reflog expire
に渡すことで実行でき、実際にはプルーニングされないように、どの reflog エントリがプルーニング対象としてマークされているかを出力します。これは、期限切れの reflog エントリをクリーンアップする際のセーフティ ネットとして役立ちます。
さらに、有効期限は、コマンドライン引数--expire=time
をgit reflog expire
に渡すか、 gc.reflogExpire
の git 構成名を設定することで指定できます。
delete サブコマンドは、その名前が示すように、渡された reflog エントリを削除します。削除は、期限切れと同様に、データ損失を引き起こす可能性があり、エンド ユーザーが頻繁に使用するものではありません。
git reflog
とgit log
は、Git が提供する名前が似ている 2 つのコンポーネントで、リポジトリのコミット履歴、ログ、および reflog に忍び込むことができます。 2 つのコンポーネントが同じ履歴を示すことが多いという事実は、特に開発者がフェッチまたはプルなしで多数のローカル コミットを完了した場合に、Git reflog とログの混乱の理由の 1 つです。
ただし、これらは本質的に異なり、使用例も異なります。
上記の 2 つのコマンドの基本的な違いと類似点を理解しましょう。
Git reflog とログの最も顕著な違いは、ログがリポジトリのコミット履歴の公開記録であるのに対し、reflog はリポジトリのローカル コミットの非公開のワークスペース固有の記録であることです。
プッシュ、フェッチ、またはプルの後、Git ログは Git リポジトリの一部として複製されます。一方、Git reflog は、複製されたリポジトリには含まれません。ローカル リポジトリが保持されているコンピューターに物理的にアクセスできないと、開発者は reflog を調べることができません。
reflog は.git\logs\refs\heads
にあるファイルで、特定のブランチのローカル コミットの履歴を追跡し、Git ガベージ コレクション プロセスによって取り除かれた可能性のあるコミットを除外します。一方、Git ログは、ブランチの履歴のコミット トラバーサルを提供します。これは、最新のコミットから始まり、ブランチの履歴の最初のコミットで終了します。
Git reflog は、reflog の概念を正しく理解していれば、コミット後にリポジトリからデータを失うことがないため、開発中のセーフティ ネットとして使用できます。意図せずに古いコミットにリセットしたり、誤ってリベースしたり、目に見えて「削除」する他の操作を実行した場合は、reflog を使用して以前の場所を確認し、 git reset --hard
を使用してその ref に戻って以前の状態に戻すことができます。コミットします。
参照は、コミット自体だけでなく、コミットの完全な履歴を参照することに注意してください。
この記事では、 git reflog
の拡張構成オプション、一般的なユースケース、およびgit reflog
の落とし穴について説明しました。
要約すると、Git は reflog を保持します。これは、 HEAD
とブランチの参照が過去数か月 (90 日間) のログであり、作業中にバックグラウンドで行われます。 Git は、何らかの理由でブランチ ヒントが変更されるたびに、この一時履歴に情報を保存します。
reflog コマンドを使用して、古すぎるエントリを reflog から削除または期限切れにすることもできます。 expire
the サブコマンドは、古い reflog エントリを削除するために使用され、 delete
サブコマンドは、reflog から削除する特定のエントリを削除および指定するために使用されます。