Запутанный бит здесь:
Git никогда не видит их как отдельные файлы. Git считает все полным содержанием.
Git часто использует 160-битные хэши вместо объектов в своем репо. Дерево файлов - это, в основном, список имен и хэшей, связанных с содержимым каждого (плюс некоторые метаданные).
Но 160-битный хеш однозначно идентифицирует контент (в юниверсе базы данных git). Таким образом, дерево с хешами в качестве содержимого включает содержимое в своем состоянии.
Если вы измените состояние содержимого файла, его хэш изменится. Но если его хеш изменяется, хеш, связанный с содержимым имени файла, также изменяется. Что, в свою очередь, изменяет хэш «дерева каталогов».
Когда база данных git хранит дерево каталогов, это дерево каталогов подразумевает и включает в себя все содержимое всех подкаталогов и все файлы в нем .
Он организован в виде древовидной структуры с (неизменяемыми, многократно используемыми) указателями на BLOB-объекты или другие деревья, но по логике он представляет собой единый снимок всего содержимого всего дерева. Представление в базе данных git не является простым содержимым данных, но логически это все данные и ничего больше.
Если вы сериализовали дерево в файловую систему, удалили все папки .git и сказали git добавить дерево обратно в его базу данных, вы бы ничего не добавили в базу данных - элемент уже будет там.
Это может помочь думать о хешах git как о подсчитываемых ссылках указателях на неизменяемые данные.
Если вы построили приложение вокруг этого, документ представляет собой набор страниц, которые имеют слои, которые имеют группы, которые имеют объекты.
Когда вы хотите изменить объект, вы должны создать для него совершенно новую группу. Если вы хотите изменить группу, вам нужно создать новый слой, для которого нужна новая страница, для которой нужен новый документ.
Каждый раз, когда вы меняете один объект, он порождает новый документ. Старый документ продолжает существовать. Новый и старый документ разделяют большую часть их содержимого - они имеют одинаковые страницы (кроме 1). Эта страница имеет одинаковые слои (кроме 1). Этот слой имеет те же группы (кроме 1). В этой группе есть те же объекты (кроме 1).
И под тем же логически я подразумеваю копию, но с точки зрения реализации это просто еще один подсчитанный ссылочный указатель на тот же неизменный объект.
Git РЕПО очень похоже на это.
Это означает, что данный набор изменений git содержит свое сообщение коммита (в виде хеш-кода), содержит свое рабочее дерево и родительские изменения.
Эти родительские изменения содержат свои родительские изменения, все назад.
Часть git-репо, которая содержит history , является этой цепочкой изменений. Эта цепочка изменений на уровне выше дерева "каталогов" - из дерева "каталогов" вы не можете однозначно получить набор изменений и цепочку изменений.
Чтобы узнать, что происходит с файлом, вы начинаете с этого файла в наборе изменений. У этого набора изменений есть история. Часто в этой истории существует один и тот же именованный файл, иногда с одинаковым содержимым. Если содержимое совпадает, файл не изменился. Если это не так, то есть изменение, и нужно разобраться, что именно.
Иногда файл исчезает; но в дереве «каталогов» может быть другой файл с тем же содержимым (с таким же хеш-кодом), поэтому мы можем отслеживать его таким образом (примечание; именно поэтому вы хотите зафиксировать перемещение файла отдельно от фиксации для -редактировать). Или то же имя файла, и после проверки файл достаточно похож.
Таким образом, git может комбинировать «историю файлов».
Но эта история файлов происходит от эффективного анализа "всего набора изменений", а не от ссылки из одной версии файла на другую.