はじめに
この実験では、Git リポジトリの履歴内に特定のファイルが存在するかどうかを確認する方法を学びます。主に 2 つの方法を探っていきます。1 つは、特定のコミットの内容を調べるために git ls-tree コマンドを使用する方法で、もう 1 つは、特定のファイルの履歴を表示するために git log コマンドにファイルパスを指定して使用する方法です。
実践的な演習を通じて、git ls-tree を使ってコミットスナップショットに含まれるファイルを調べ、git log -- <file> を使ってファイルの存在と履歴を確認する練習を行います。また、存在しないファイルでこれらの方法をテストし、その動作を理解します。
git ls-tree を実行してファイルを確認する
このステップでは、git ls-tree コマンドを使って Git のタイムマシンの中身を調べる方法を学びます。このコマンドを使うと、特定のコミットの内容を確認できます。まるで密閉されたタイムカプセルを完全に開けずに中身を見るようなものです。
まず、プロジェクトディレクトリにいることを確認しましょう。
cd ~/project/my-time-machine
次に、git ls-tree を使って最新のコミットの内容を確認しましょう。コミット ID が必要ですが、これは git log の出力から取得できます。また、HEAD を使って最新のコミットを指定することもできます。
git ls-tree HEAD
以下のような出力が表示されるはずです。
100644 blob a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9 message.txt
この出力を分解してみましょう。
100644: これはファイルモードで、通常のファイルであることを示しています。blob: これは、Git での「ブロブ (blob)」オブジェクトであることを示しています。ブロブは、Git がファイルの内容を保存する方法です。a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9: これはブロブオブジェクトの一意の識別子 (ハッシュ) で、コミット時点でのmessage.txtファイルの正確な内容を表しています。message.txt: これはファイル名です。
git ls-tree コマンドは、コミットをチェックアウトせずにその内容を調べるのに便利です。特定の時点のスナップショットに含まれていたファイルやディレクトリを表示します。これは、最新のコミットと比較して作業ディレクトリの現在の状態を表示する git status とは異なります。
git ls-tree を理解することで、Git がプロジェクトの履歴を一連のスナップショットとして保存し、それぞれに独自のファイルとディレクトリのセットがあることを確認できます。
git log -- ファイル を使って検証する
前のステップでは、git ls-tree を使ってコミットの内容を確認しました。今度は、ファイルパスを指定して git log を使い、特定のファイルに関連する履歴を表示する別の方法を探ってみましょう。
まだプロジェクトディレクトリにいることを確認してください。
cd ~/project/my-time-machine
次に、git log を使って message.txt ファイルの履歴を表示しましょう。
git log -- message.txt
message.txt を作成したコミットのログエントリが表示されるはずです。
commit a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9 (HEAD -> master)
Author: Your Name <your.email@example.com>
Date: Mon Aug 7 10:00:00 2023 +0000
Send a message to the future
コマンドの -- message.txt の部分は、git log に message.txt ファイルに影響を与えたコミットのみを表示するよう指示します。多数のファイルがある大規模なプロジェクトで、特定のファイルの履歴のみを見たい場合に非常に便利です。
このコマンドは、以下のような質問に答えるのに役立ちます。
- このファイルはいつ作成されたか?
- このファイルに最後の変更を加えたのは誰か?
- 特定のコミットでこのファイルに加えられた変更は何か?
プロジェクトが拡大し、コミットが増えるにつれて、git log -- <file> を使ってプロジェクト内の個々のファイルの履歴と進化を理解することが不可欠になります。
ログビューを終了するには、q を押してください。
存在しないファイルをテストする
前のステップでは、git ls-tree と git log -- <file> を使って、Git リポジトリに存在するファイルを調べることに成功しました。では、リポジトリの履歴に存在しないファイルにこれらのコマンドを適用した場合、どうなるか見てみましょう。
プロジェクトディレクトリにいることを確認してください。
cd ~/project/my-time-machine
まず、存在しないファイル(例えば nonexistent.txt)に git ls-tree を適用してみましょう。
git ls-tree HEAD nonexistent.txt
何も出力されないはずです。これは、git ls-tree が指定されたツリー(この場合は HEAD のツリー)に存在するエントリのみをリストするためです。nonexistent.txt は最新のコミットのツリーに存在しないため、何も表示されません。
次に、同じ存在しないファイルに git log を適用してみましょう。
git log -- nonexistent.txt
以下のような出力が表示されるはずです。
fatal: no such path 'nonexistent.txt' in HEAD
これは異なる動作です!git log -- <file> は、履歴全体を通じて指定されたファイルパスに影響を与えたコミットを探します。もしそのファイルパスがどのコミットにも存在しない場合、Git は「そのようなパスは存在しません」と教えてくれます。
この動作の違いは、これらのコマンドがどのように機能するかを明確に示しています。
git ls-treeは、特定のスナップショット(コミット)を調べ、その内容をリストします。git log -- <file>は、特定のファイルパスに関連する変更を履歴全体から検索します。
これらの違いを理解することで、タスクに適したコマンドを選ぶことができます。コミットに含まれていたファイルを確認したい場合は git ls-tree を使い、ファイルの履歴を確認したい場合は git log -- <file> を使いましょう。
まとめ
この実験では、特定のコミットをチェックアウトすることなく、Git リポジトリの履歴内にファイルが存在するかどうかを確認する方法を学びました。まず、git ls-tree コマンドを調べました。このコマンドを使うと、特定のコミット(例えば HEAD)の内容を調べ、ファイルとそれに対応するブロブのハッシュを確認できます。このコマンドは、特定の時点でのリポジトリのスナップショットを提供し、ファイルモード、オブジェクトタイプ、オブジェクト ID、およびファイル名を表示します。
次に、ファイルパスを指定して git log を使い、そのファイルに関連するコミット履歴を表示する方法を調べ始めました。この方法を使うと、ファイルが追加、変更、または削除された時期を確認でき、リポジトリのタイムライン内でのファイルの存在について別の視点を提供します。



