あるファイルから別のファイルに単一の関数を移動すると、Gitがそれを追跡できるという声明に何度か出くわしました。たとえば、このエントリには、「関数をあるファイルから別のファイルに移動すると、Gitは移動中のその単一の関数の履歴を教えてくれるとLinusは言っています」と書かれています。
しかし、私はGitの内部設計のいくつかに少し気づいており、これがどのように可能であるかわかりません。だから私は疑問に思っています...これは正しいステートメントですか?もしそうなら、これはどのように可能ですか?
私の理解では、Gitは各ファイルのコンテンツをBlobとして保存し、各Blobは、そのコンテンツとサイズのSHAハッシュから生じるグローバルに一意のIDを持っています。次に、Gitはフォルダーをツリーとして表します。ファイル名情報はすべてBlobではなくTreeに属しているため、たとえばファイル名の変更は、BlobではなくTreeへの変更として表示されます。
したがって、20個の関数を含む「foo」というファイルと5個の関数を含む「bar」というファイルがあり、関数の1つをfooからbarに移動すると(それぞれ19と6になります)、その関数をあるファイルから別のファイルに移動したことをGitはどのように検出できますか?
私の理解では、これにより2つの新しいblobが存在します(1つは変更されたfoo用、もう1つは変更されたbar用)。関数が1つのファイルから別のファイルに移動されたことを示すためにdiffを計算できることに気付きました。しかし、関数に関する履歴がfooではなくbarに関連付けられる可能性があるかどうかはわかりません(とにかく自動的ではありません)。
Gitが実際に単一のファイルの内部を調べ、関数ごとにblobを計算する場合(可能な言語を解析する方法を知っている必要があるため、これはクレイジー/実行不可能です)、これがどのように可能であるかがわかります。
それで...ステートメントは正しいかどうか?そしてそれが正しければ、私の理解に欠けているものは何ですか?