Как git отслеживать исходный код между файлами?

По-видимому, когда вы перемещаете функцию из одного исходного файла кода в другой, журнал изменений git (для нового файла) может показать вам, откуда этот исходный код был изначально (см., например, раздел "Просмотр истории" в этот учебник).

Как это работает?

Ответ 1

Он не отслеживает их. Это его красота.

Git записывает только моментальные снимки всего дерева проектов: вот как выглядели все файлы перед фиксацией и вот как они выглядят после. Как мы добрались сюда, Git не заботится.

Это позволяет создавать интеллектуальные инструменты после того, как команда совершила ошибку, чтобы извлечь информацию из этой фиксации. Например, определение переименования в Git выполняется путем сравнения всех удаленных файлов со всеми новыми файлами и сравнения парных показателей сходства. Если метрика подобия больше, чем x, они считаются переименованными, если она находится между y и x (y < x), она считается переименованием + редактировать, а если она меньше y, они считаются независимыми. Самое приятное, что вы, как "археолог-фиксатор", можете указать после факта, что должны быть x и y. Это не сработает, если коммит просто записал "этот файл является переименованием этого файла".

Обнаружение перемещенного содержимого работает аналогично: вы нарезаете каждый файл на куски, вычисляете метрики подобия между всеми срезами и затем можете вывести, что этот фрагмент, который был удален здесь, и этот очень похожий фрагмент, который был добавлен там, фактически является одним и тем же фрагментом который был перемещен отсюда туда.

Однако, как сказал tonfa в своем ответе, это очень дорого, поэтому обычно это не делается. Но это можно сделать, и что точка.

BTW: это в значительной степени противоположно модели операционного преобразования, используемой Google Wave, EtherPad, Gobby, SubEthaEdit, ACE и Co.

Ответ 2

Это чисто эвристика. Он сравнивает расстояние между файлами и пытается найти соответствующие блоки. Но эта эвристика реализована только тогда, когда код скопирован или перенесен в новый файл (иначе это было бы слишком дорого, проверяя каждую пару файлов).