автор:Фэн Вэйяо
Когда мы переключаемся между разными ветвями или переключаемся на указанную историческую запись коммита, как Git вызывает историческую версию файла? То есть:
- Где Git хранит данные?
- Как хранить разные версии файлов?
- Как связать разные версии с указанными записями фиксации?
Прежде чем мы начнем, во избежание некоторых неясностей, давайте унифицируем наше понимание записей фиксации: все мы знаем, что каждая запись фиксации будет иметь уникальную соответствующую 40-битную строку, которая вычисляется Git с использованием алгоритма SHA-1 на основе нашего зафиксировать содержимое из хеш-значения. Эта 40-битная строка называется идентификатором, или хеш-значением, или контрольной суммой, или значением SHA-1. Поскольку SHA-1 — это хеш-алгоритм, здесь мы унифицируем, эта строка называетсяхэш-значение.
Как Git хранит данные
Как Git хранит данные, ответ в основном находится в каталоге объектов папки .git. Не объясняя, что такое каталог объектов, давайте посмотрим, что в нем находится. Теперь вы можете открыть репозиторий Git по желанию и найти папку объектов в каталоге .git (который по умолчанию может быть скрыт). Он должен выглядеть так:
Есть много папок с именами из 2 символов, и есть несколько файлов, названных в честь строки из 38 символов в папке. Если вы достаточно чувствительны, вы, вероятно, можете догадаться, что это хеш-значение, похожее на указанную запись коммита. с помощьюgit cat-file
Команда для просмотра содержимого этого файла. Результат выглядит следующим образом:
Результатом является содержимое файла CHANGELOG.md в моем проекте. Скорее, это все содержимое файла CHANGELOG.md при фиксации. а такжеВ этой папке объектов Git хранит данные.
Каждый раз, когда Git фиксируется, он находит измененный файл и использует алгоритм SHA-1 для вычисления 40-битной строки в соответствии с содержимым, чтобы назвать файл и поместить его в папку объектов. Первые два символа хэша используются для имени подкаталога, а остальные 38 символов используются как имя файла.Другими словами, каждый раз, когда ваш файл изменяется, будет создаваться соответствующий снимок, сохраняющий все содержимое этой версии файла. Если Git хочет восстановить файл до определенной исторической версии, ему нужно только получить хеш-значение, соответствующее текущей версии файла.
Но как Git узнает, какое хеш-значение соответствующей версии файла при фиксации? То есть, как Git связывает разные версии файлов с записями коммитов?
На самом деле, в папке объектов в основном хранятся три типа информации.В дополнение к информации о содержимом файла, о которой мы упоминали выше, есть также информация о пути к файлу и информация о представлении.Они существуют в форме объекта BLOB-объекта файлового объекта, объекта дерева объекта дерева и объекта фиксации объекта фиксации соответственно. Каждый объект представляет собой файл в каталоге объектов.Подобно способу сохранения информации о содержимом файла, Git вычисляет значение хеш-функции на основе содержимого объекта с помощью алгоритма SHA-1 и получает строку из 40-битных строк для имени объекта. файл, который используется для имени файла, найдите их.Далее давайте посмотрим, что содержат объект дерева и объект фиксации.
Когда вы сделаете коммит, Git сохранит вашу текущую структуру каталогов.Соответствующая древовидная структура объектов выглядит следующим образом:
Содержит имя файла и хеш-значение файлового объекта, а также имя подпапки и соответствующее хэш-значение объекта дерева. То есть,Вам нужно только найти хеш-значение объекта дерева корневого каталога фиксации, а затем вы можете найти имена файлов и хэш-значения файловых объектов, соответствующие всем файлам в этой фиксации.Вы также можете получить историческую версию содержимого файла.
Итак, как мне найти этот объект дерева?
Именно через объект фиксации мы наиболее знакомы.git log
Команда может найти хеш-значение соответствующего коммита.Мы видим, что структура объекта фиксации выглядит следующим образом:
tree указывает на текущий зафиксированный объект дерева. parent — это объект фиксации последней фиксации. Остальные - автор, отправитель, время и описательная информация.
Теперь я могу знать, какова историческая версия содержимого определенного файла для определенного коммита. Из этого мы также примерно понимаем, как Git хранит исторические версии файлов и как связать исторические версии с записями коммитов.
При фиксации с помощью git commit Git сначала вычисляет хэш каждого подкаталога, а затем сохраняет эти контрольные суммы в виде объектов дерева в репозитории Git. Затем Git создает объект коммита, который, помимо информации об авторе, времени и описании, также содержит хэш, указывающий на этот объект дерева (корень проекта), и хэш последнего коммита. Таким образом, Git может воспроизвести этот сохраненный снимок, когда это необходимо.
ветка git
Теперь мы знаем, что если мы получаем хеш-значение объекта фиксации, мы можем получить моментальный снимок, соответствующий этой фиксации. Если нам нужно содержимое файла ветки, как нам это сделать?
Ветка — это просто изменяемый указатель на последний объект фиксации ветки.
В папке refs в .git сохраняется хеш-значение последнего объекта коммита, соответствующего всем веткам. Структура каталогов следующая:
Папка head содержит локальные ветки, а папка remotes — удаленные ветки. Возьмем в качестве примера мастер локальной ветки, используяcat master
Как видите, в этом файле хранится хэш последнего объекта коммита. Если вы сделаете новую фиксацию сейчас, вы обнаружите, что содержимое файла станет хешем нового объекта фиксации.
в то же времяВ Git есть специальная ссылка HEAD, которая всегда указывает на проверенную в данный момент ветку или объект коммита. Объект фиксации, на который указывает HEAD, хранится в файле HEAD в .git.Как показано ниже, HEAD указывает на главную ветку. Если мы вручную проверим последний коммит ветки master, то обнаружим, что файл указывает на некий объект коммита, то есть объект коммита последнего коммита.
Наконец, график можно использовать для обобщения взаимосвязи между ветвями и объектами фиксации.