Это настоящий Git - Git внутренний принцип

Git

TL;DR

Эта статья знакомит с внутренними принципами Git на конкретном примере в сочетании с анимацией, в том числе о том, что Git хранит наш код и историю изменений, как Git изменяется при изменении файла, каковы преимущества Git, реализованного таким образом, и т. д. Объясните приведенную выше анимацию на примере, чтобы каждый мог понять внутренние принципы Git. Если вы уже можете понять эту картинку, следующее содержание может быть для вас более базовым.


Эта статья представляет собой текстовую версию, представленную на сеансе обмена интерфейсом FCC (freeCodeConf 2019 Shenzhen Station), который проходил в многоцелевом зале на 2-м этаже Shenzhen Tencent Building 24 ноября 2019 г.

видео:воооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооо

РРТ:Woohoo. Laozaner.com//git-U в руке…

предисловие

В последние годы технологии развиваются очень быстро, и у некоторых школьников выработалась привычка изучать знания только на поверхности и только вызывая какие-то инструкции. У нас часто возникает иллюзия «Я буду использовать эту технологию и этот фреймворк», и когда мы действительно сталкиваемся с проблемами, мы понимаем, что все не так просто.

И Git — это тоже такая штука, что большинство людей знают, как им пользоваться и какие есть команды, но лишь немногие знают конкретные принципы. Знание некоторых низкоуровневых вещей может лучше помочь вам прояснить свои мысли, понять, что вы действительно работаете, и не потеряться в большом количестве инструкций и параметров Git.

Как Git хранит информацию

Здесь мы воспользуемся простым примером, чтобы каждый интуитивно почувствовал, как git хранит информацию.

Сначала создаем два файла

$ git init
$ echo '111' > a.txt
$ echo '222' > b.txt
$ git add *.txt

Git будет хранить всю базу данных в.git/директорию, если зайти посмотреть в это время.git/objectsкаталог, вы найдете еще два объекта на складе.

$ tree .git/objects
.git/objects
├── 58
│   └── c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c
├── c2
│   └── 00906efd24ec5e783bee7f23b5d7c941b0c12c
├── info
└── pack

Любопытно, давайте посмотрим, что там

$ cat .git/objects/58/c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c
xKOR0a044K%

Почему это строка искаженных символов? Это связано с тем, что Git сжимает информацию в двоичные файлы. Но не волнуйтесь, потому что Git также предоставляет API, который может помочь вам изучить его.git cat-file [-t] [-p],-tВы можете просмотреть тип объекта,-pВы можете просматривать конкретное содержимое хранилища объектов.

$ git cat-file -t 58c9
blob
$ git cat-file -p 58c9
111

Можно обнаружить, что этот объект является узлом типа blob, а его содержимое равно 111, что означает, что этот объект хранит содержимое файла .txt.

Здесь мы сталкиваемся с первым объектом Git, типом blob, который хранит только содержимое файла, исключая другую информацию, такую ​​как имя файла. Затем передайте информацию через хэш-алгоритм SHA1, чтобы получить соответствующее значение хеш-функции. 58c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c, как единственный идентификатор этого объекта в репозитории Git.

То есть наш репозиторий Git на данный момент выглядит так:

Продолжая исследовать, мы создаем коммит.

$ git commit -am '[+] init'
$ tree .git/objects
.git/objects
├── 0c
│   └── 96bfc59d0f02317d002ebbf8318f46c7e47ab2
├── 4c
│   └── aaa1a9ae0b274fba9e3675f9ef071616e5b209
...

Мы обнаружим, что когда наша фиксация будет завершена, в репозитории Git есть еще два объекта. использовать то же самоеcat-fileКомандование, давайте посмотрим, какого они типа и каково конкретное содержание.

$ git cat-file -t 4caaa1
tree
$ git cat-file -p 4caaa1
100644 blob 58c9bdf9d017fcd178dc8c0... 	a.txt
100644 blob c200906efd24ec5e783bee7...	b.txt

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

Репозиторий Git на данный момент выглядит так:

$ git cat-file -t 0c96bf
commit
$ git cat-file -p 0c96bf
tree 4caaa1a9ae0b274fba9e3675f9ef071616e5b209
author lzane 李泽帆  1573302343 +0800
committer lzane 李泽帆  1573302343 +0800
[+] init

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

На данный момент мы смотрим на репозиторий Git следующим образом:

На данный момент мы знаем, как Git хранит предоставленную информацию.Тогда некоторые студенты спросят, где информация о ветке, с которой мы обычно связываемся?

$ cat .git/HEAD
ref: refs/heads/master

$ cat .git/refs/heads/master
0c96bfc59d0f02317d002ebbf8318f46c7e47ab2

В репозитории Git HEAD, ветвь и обычный тег можно просто понимать как указатель на значение SHA1 соответствующего коммита.

На самом деле есть четвертый объект Git, тип tag, при добавлении тега с примечанием (git tag -a), он будет создан заново. Здесь он не будет подробно описываться. Заинтересованные друзья могут подробно изучить его в соответствии с описанными выше методами.

Пока мы знаем, что Git хранит содержимое файла, структуру каталогов, информацию о фиксации и ветки.По сути, это база данных «ключ-значение» плюс ориентированный ациклический граф (DAG), сформированный деревом Меркла.. Здесь вы можете взглянуть на популярность блокчейна, Структура данных блокчейна также использует дерево Меркла.

Три раздела Git

Далее давайте рассмотрим три раздела Git (рабочий каталог, индексная область, репозиторий Git) и то, как формируются записи изменений Git. Поняв внутренние принципы этих трех разделов и цепочки Git, вы сможете «визуально» понять многие инструкции Git, и вас больше не будет сбивать с толку.

Следуя приведенному выше примеру, текущий статус склада выглядит следующим образом:

Здесь есть три области, и информация, которую они хранят:

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

Посмотрим, что происходит в процессе обновления содержимого файла.

бегатьecho "333" > a.txtИзмените содержимое файла .txt со 111 на 333. В настоящее время, как вы можете видеть на рисунке выше, в настоящее время нет никаких изменений в области индекса и репозитории git.

бегатьgit add a.txtДобавьте .txt в область индекса.В это время, как показано на рисунке выше, git создает новый объект большого двоичного объекта в хранилище для хранения нового содержимого файла. И обновил индекс, чтобы указать a.txt на вновь созданный объект большого двоичного объекта.

бегатьgit commit -m 'update'Отправьте эту редакцию. Как показано на фиг.

  1. Git сначала создает объект дерева на основе текущего индекса, который действует как снимок нового коммита.
  2. Создайте новый объект фиксации, сохраните информацию об этой фиксации, а родитель указывает на предыдущую фиксацию, формируя цепочку для записи истории изменений.
  3. Переместите указатель главной ветки на новый узел фиксации.

На данный момент мы знаем, что такое три раздела Git, их функции и как устанавливается цепочка истории. ** В основном большинство инструкций Git работают с этими тремя разделами и этой цепочкой.Вы можете попробовать подумать о различных командах git и посмотреть, сможете ли вы разместить их на картинке выше.Выходит "Визуализация", это очень важно, рекомендуется попробовать.

Если вы не можете «визуализировать» инструкции, которыми пользуетесь каждый день, рекомендуется прочитатьГрафический git


Подпишитесь на официальный аккаунт [IVWEB Community], чтобы еженедельно узнавать о новейших технологиях, сегодня вы лучше, чем вчера!


несколько интересных вопросов

Заинтересованные студенты могут продолжить чтение, эта часть не является основным содержанием статьи.

Вопрос 1. Почему права доступа к файлам и имена файлов должны храниться в объекте дерева, а не в объекте большого двоичного объекта?

Представьте себе изменение имени файла.

Если имя файла хранится в большом двоичном объекте, Git может скопировать только еще одно исходное содержимое, чтобы сформировать новый объект большого двоичного объекта. Метод реализации Git требует только создания нового объекта дерева и изменения соответствующего имени файла на новое.Исходный объект большого двоичного объекта можно использовать повторно, экономя место.

Вопрос 2. Сохраняет ли Git для каждого коммита новый снимок файла или измененные части файла?

Как видно из приведенного выше примера, Git хранит свежий снимок файла, а не журнал изменений файла. То есть, даже если вы просто добавите строку в файл, Git создаст новый объект blob. Разве это не пустая трата места?

На самом деле это компромисс между Git с точки зрения пространства и времени.Подумайте, хотите ли вы проверить коммит или сравнить различия между двумя коммитами. Если Git хранит измененную часть анкеты, чтобы получить содержимое коммита, Git может начать только с первого коммита, а затем продолжать вычислять изменения до целевого коммита, что займет много времени. И наоборот, подход Git к хранению свежих моментальных снимков файлов делает это моментальным, просто извлекая содержимое из моментального снимка.

Конечно, когда задействована передача по сети или репозиторий Git действительно велик, в Git есть механизм сборки мусора gc, который не только удаляет бесполезные объекты, но и упаковывает и сжимает существующие аналогичные объекты.

Вопрос 3. Как Git гарантирует, что исторические записи нельзя будет подделать?

Гарантируется хеш-алгоритмом SHA1 и хеш-деревом. Предположим, вы тайно модифицируете содержимое предыдущего файла в записи истории изменений, тогда изменится хеш-значение SHA1 объекта blob этой анкеты, также необходимо изменить SHA1 связанного объекта дерева, и SHA1 коммита Также необходимо изменить этот коммит Все последующие значения коммита SHA1 также будут изменены соответствующим образом. А поскольку Git — это распределенная система, то есть у каждого есть Git-репозиторий с полной историей, поэтому каждый может легко найти проблемы.


Я надеюсь, что вы узнали что-то после ее прочтения.В следующей статье будут описаны некоторые навыки работы с Git, которые я считаю полезными в своей повседневной работе, часто задаваемые вопросы и способы борьбы с некоторыми авариями.

Ссылаться на