Git отслеживает содержимое файла, а не имена файлов. Таким образом, git легко обнаружит переименование файла без изменения его содержимого. (Git не отслеживает, но выполняет обнаружение ; использование git mvили git rmи git addфактически одно и то же.)
Когда файл добавляется в репозиторий, имя файла находится в объекте дерева. Фактическое содержимое файла добавляется в репозиторий в виде большого двоичного объекта ( blob ). Git не будет добавлять еще один большой двоичный объект для дополнительных файлов с таким же содержимым. Фактически, Git не может, поскольку содержимое хранится в файловой системе, причем первые два символа хеша являются именем каталога, а остальные - именем файла в нем. Итак, чтобы обнаружить переименования, нужно сравнить хеши.
Чтобы обнаружить небольшие изменения в переименованном файле, Git использует определенные алгоритмы и пороговое значение, чтобы увидеть, является ли это переименованием. Например, посмотрите на -Mфлаг для git diff. Существуют также значения конфигурации, такие как merge.renameLimit(количество файлов, которые следует учитывать при выполнении обнаружения переименования во время слияния).
Чтобы понять, как git обрабатывает похожие файлы (т. Е. Какие преобразования файлов считаются переименованием), изучите доступные параметры конфигурации и флаги, как упоминалось выше. Не нужно думать о том, как. Чтобы понять, как git на самом деле выполняет эти задачи, просмотрите алгоритмы поиска различий в тексте и прочтите исходный код git.
Алгоритмы применяются только для целей сравнения, слияния и ведения журнала - они не влияют на то, как git их хранит. Любое небольшое изменение содержимого файла означает, что для него добавляется новый объект. На этом уровне не происходит никаких дельт или различий. Конечно, позже объекты могут быть упакованы там, где дельты хранятся в файлах пакетов, но это не связано с обнаружением переименования.