1. ホーム
  2. git

Git は、あるファイルから別のファイルへの関数の移動を本当に追跡できるのでしょうか?もしそうなら、どうやって?

2023-09-18 02:56:33

質問

ある一つの関数をあるファイルから別のファイルに移動させると、Git はそれを追跡できるという記述に何度か出くわしました。例えば このエントリ には、"Linusが、ある関数をあるファイルから別のファイルに移動すると、Gitはその移動に伴う関数の履歴を教えてくれると言っています。

しかし、私はGitのアンダーザフッド設計のいくつかを少し意識していますが、これがどのように可能なのかわかりません。そこで疑問なのですが、これは正しい記述なのでしょうか?そしてもしそうなら、これはどのように可能なのでしょうか?

私の理解では、Git は各ファイルのコンテンツを Blob として保存し、各 Blob はそのコンテンツとサイズの SHA ハッシュから生じるグローバルにユニークな ID を持っています。そして、Git はフォルダーをツリーとして表します。ファイル名の情報はすべてツリーに属し、Blobには属しません。したがって、例えばファイルのリネームは、Blobではなくツリーへの変更として表示されます。

20個の関数が入った "foo" というファイルと、5個の関数が入った "bar" というファイルがあり、foo から bar に関数を移動させたとします(結果はそれぞれ19と6になります)。

私の理解では、これは2つの新しいブロブ(1つは変更されたfooのため、もう1つは変更されたbarのため)の存在を引き起こすでしょう。私は、関数が 1 つのファイルから別のファイルに移動されたことを示すために diff を計算することができることを理解しています。しかし、関数に関する履歴がどのように foo ではなく bar に関連付けられるかはわかりません (とにかく、自動的ではありません)。

もしGitが実際に の内部を を計算し ブロブを計算します。 (を計算する(これは、あらゆる言語を解析する方法を知っていなければならないため、クレイジーで実行不可能です)ことができれば、これがどのように可能であるかを理解できます。

では......この文は正しいのでしょうか、そうでないのでしょうか?そして、もし正しいのであれば、私の理解で何が欠けているのでしょうか?

どのように解決するのですか?

この機能は git blame -C <file> .

-C オプションは、レビュー中のファイルのテキストの追加や削除と、同じチェンジセットで変更されたファイルとの間のマッチングを探そうとするように git を動かします。追加 -C -C または -C -C -C は検索を拡張する。

を使って、テストレポで試してみてください。 git blame -C で試してみると、移動したコードのブロックが元のファイルに由来していることがわかるでしょう。

から git help blame のマニュアルページをご覧ください。

行の起点は、ファイル全体のリネームにわたって自動的に追跡されます (現在のところ、リネームへの追跡をオフにするオプションはありません)。あるファイルから別のファイルへ移動した行や、別のファイルからコピー&ペーストされた行などを追いかけるには -C-M のオプションがあります。