С точки зрения пользователя, естественно считать коммит «содержащим» файлы, но внутренне точнее сказать, что коммит «ссылается» на файлы.
По своей сути, git - это хранилище объектов с индексированным содержимым: существует множество объектов, каждый из которых уникально идентифицируется по их хэшу SHA1. Поверх этого хранилища объектам дано значение, представляющее компоненты системы контроля версий.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Хорошее введение.
Итак, когда вы фиксируете файл, сохраняется несколько объектов:
- Объект «blob», содержащий содержимое файла, без метаданных
- Объект «дерево», содержащий список каталогов, с именем и метаданными для каждого файла, а также хэш SHA1 его текущего содержимого
- Объект "commit", представляющий коммит, включая сообщение о коммите, время коммита, хэши SHA1 родительского коммита (ов) и хеш SHA1 списка каталогов для использования
SHA1, который вы обычно видите, является SHA1 этого объекта коммита - зная, что этого достаточно для git, чтобы найти полную информацию о коммите и оттуда найти список каталогов и оттуда содержимое файла.
Когда вы выбираете коммит, git нужно будет создать:
- Новый объект коммита с новым временем, родительским коммитом (ами) и т. Д.
- Возможно, новый объект дерева, в результате слияния выбранных изменений, вероятно, приведет к тому, что некоторые файлы будут другими
- Новые объекты BLOB-объектов для любого файла с новым содержимым ; если большой файл имеет содержимое, идентичное любому предыдущему состоянию, он по определению будет иметь тот же хэш SHA1, поэтому не будет снова сохранен
В некотором смысле, git не здесь "умный" - ему все равно почему объект может дублироваться, он просто хранит один объект для каждого хеша SHA1, и если он обнаруживает, что объект уже существует с этим хешем, предполагается, что это одно и то же. Возможность для нескольких, возможно, не связанных, коммитов ссылаться на одно и то же содержимое файла просто выпадает как удобный побочный эффект этой системы хранения.