Подтвердить что ты не робот

Может ли Git действительно отслеживать перемещение одной функции из одного файла в другой? Если да, то как?

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

Но у меня есть немного понимания некоторых из Git дизайна под капотом, и я не вижу, как это возможно. Так что мне интересно... это правильное утверждение? И если да, то как это возможно?

Мое понимание заключается в том, что Git хранит каждое содержимое файла как Blob, и каждый Blob имеет уникальную глобальную идентификацию, которая возникает из хэша SHA его содержимого и размера. Git затем представляет папки как деревья. Любая информация о имени файла принадлежит дереву, а не к Blob, поэтому переименование файла, например, отображается как изменение дерева, а не в Blob.

Итак, если у меня есть файл с именем "foo" с 20 функциями в нем и файл под названием "bar" с 5 функциями в нем, и я перехожу одну из функций из foo в bar (в результате получается 19 и 6, соответственно), как Git обнаружить, что я переместил эту функцию из одного файла в другой?

По моему мнению, это приведет к появлению 2 новых blobs (один для измененного foo и один для модифицированного бара). Я понимаю, что diff можно рассчитать, чтобы показать, что функция была перенесена из одного файла в другой. Но я не вижу, как история о функции может стать ассоциированной с баром, а не foo (не автоматически, во всяком случае).

Если Git должен был заглянуть внутрь отдельных файлов и вычислить blob для каждой функции (что было бы сумасшедшим/неосуществимым, потому что вам нужно было бы знать, как разбирать любой возможный язык), тогда я мог видеть, как это возможно.

Итак... утверждение правильное или нет? И если это правильно, то чего не хватает в моем понимании?

4b9b3361

Ответ 1

Эта функция предоставляется через git вину -C

Опция -C устанавливает git в попытку найти совпадения между добавлением или удалением фрагментов текста в просматриваемом файле и файлы, измененные в тех же наборах изменений. Дополнительно -CC или -CCC расширяют поиск. Введите git справку об ошибке на странице руководства.

Попробуйте себя в тестовом репо с git вином -C, и вы увидите, что блок кода, который вы только что переместили, возник в исходном файле, где он принадлежал.

Ответ 2

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

То, что я действительно хотел бы, это дать git log, как некоторый аргумент, номер строки диапазона дополнительно к пути к файлу, а затем он покажет историю этого кодового блока. Такой вариант отсутствует, если документация правильная. Да, из заявления Линуса я тоже думаю, что такая команда должна быть легко доступна.

Ответ 3

От Git 2.15, git diff теперь поддерживает обнаружение перемещенных строк с опцией --color-moved. Он работает для перемещения по файлам.

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

Для поведения по умолчанию попробуйте

git diff --color-moved

Команда также принимает опции, которые в настоящее время являются no, default, plain, zebra и dimmed_zebra (используйте git help diff для получения последних опций и их описаний). Например:

git diff --color-moved=zebra

В отношении того, как это делается, вы можете получить некоторое понимание от этот обмен электронной почтой автором функциональности.

Ответ 4

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

Таким образом, функции переименования функций отслеживания - это простой вопрос анализа различий всех файлов в каждой фиксации после факта. В этом нет ничего невозможного; существующее отслеживание переименования уже обрабатывает "нечеткие" переименования, в которых некоторые изменения выполняются в файле, а также переименовываются; это требует просмотра содержимого файлов. Это было бы простое расширение для поиска переименований функций.

Я не знаю, действительно ли базовые инструменты git делают это, но они стараются быть нейтральными по отношению к языку, а идентификация функций очень не является нейтральной для языка.

Ответ 5

Там git diff, который покажет вам, что некоторые строки исчезли из foo и снова появились в bar. Если в этих файлах нет других изменений в этих файлах, это изменение будет легко распознано.

Интеллектуальный клиент git сможет показать вам, как строки перемещаются из одного файла в другой. Языковая среда IDE сможет соответствовать этому изменению с помощью определенной функции.

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