Несколько раз я сталкивался с утверждением, что, если вы переместите одну функцию из одного файла в другой, Git сможет отследить ее. Например, эта запись гласит: «Линус говорит, что если вы переместите функцию из одного файла в другой, Git расскажет вам историю этой отдельной функции при перемещении».
Но я немного осведомлен о некоторых конструкциях Git под капотом, и я не понимаю, как это возможно. Так что мне интересно ... это правильное утверждение? И если да, то как это возможно?
Насколько я понимаю, Git хранит содержимое каждого файла в виде BLOB-объекта, и каждый BLOB-объект имеет глобально уникальную идентичность, которая возникает из хэша SHA его содержимого и размера. Затем Git представляет папки как деревья. Любая информация об имени файла принадлежит дереву, а не BLOB-объекту, поэтому переименование файла, например, отображается как изменение дерева, а не BLOB-объекта.
Так что, если у меня есть файл с именем «foo» с 20 функциями в нем и файл с именем «bar» с 5 функциями в нем, и я перемещаю одну из функций из foo в bar (в результате получаем 19 и 6, соответственно), как Git может обнаружить, что я переместил эту функцию из одного файла в другой?
Насколько я понимаю, это приведет к появлению 2 новых BLOB-объектов (один для модифицированного foo и один для модифицированного бара). Я понимаю, что разница может быть рассчитана, чтобы показать, что функция была перемещена из одного файла в другой. Но я не вижу, как история о функции могла бы ассоциироваться с bar вместо foo (во всяком случае, не автоматически).
Если бы Git действительно посмотрел внутри отдельных файлов и вычислил блоб для каждой функции (что было бы сумасшедшим / неосуществимым, потому что вам нужно было бы знать, как анализировать любой возможный язык), тогда я мог видеть, как это возможно.
Итак ... это утверждение правильно или нет? И если это правильно, то чего не хватает в моем понимании?