Как git обнаруживает похожие файлы для обнаружения переименования?

92

Википедия объясняет автоматическое определение переименования:

Вкратце, учитывая файл в редакции N, файл с тем же именем в редакции N-1 является его предком по умолчанию. Однако, когда в ревизии N-1 нет файла с таким же именем, Git ищет файл, который существовал только в ревизии N-1 и очень похож на новый файл.

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

Mahemoff
источник
См. Также: stackoverflow.com/questions/13805750/…
Trilarion 04

Ответы:

93

Git отслеживает содержимое файла, а не имена файлов. Таким образом, git легко обнаружит переименование файла без изменения его содержимого. (Git не отслеживает, но выполняет обнаружение ; использование git mvили git rmи git addфактически одно и то же.)

Когда файл добавляется в репозиторий, имя файла находится в объекте дерева. Фактическое содержимое файла добавляется в репозиторий в виде большого двоичного объекта ( blob ). Git не будет добавлять еще один большой двоичный объект для дополнительных файлов с таким же содержимым. Фактически, Git не может, поскольку содержимое хранится в файловой системе, причем первые два символа хеша являются именем каталога, а остальные - именем файла в нем. Итак, чтобы обнаружить переименования, нужно сравнить хеши.

Чтобы обнаружить небольшие изменения в переименованном файле, Git использует определенные алгоритмы и пороговое значение, чтобы увидеть, является ли это переименованием. Например, посмотрите на -Mфлаг для git diff. Существуют также значения конфигурации, такие как merge.renameLimit(количество файлов, которые следует учитывать при выполнении обнаружения переименования во время слияния).

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

Алгоритмы применяются только для целей сравнения, слияния и ведения журнала - они не влияют на то, как git их хранит. Любое небольшое изменение содержимого файла означает, что для него добавляется новый объект. На этом уровне не происходит никаких дельт или различий. Конечно, позже объекты могут быть упакованы там, где дельты хранятся в файлах пакетов, но это не связано с обнаружением переименования.

Manojlds
источник
59
«Не нужно думать о том, как». - Я думал, это был вопрос?
баня
2

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

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

ГолезТрол
источник