Репозиторий Git использует простое хранилище типа ключ-значение, где в роли ключа выступает хеш SHA-1, а значение представляет собой контейнер одного из трех типов: описание коммита, описание дерева файлов или содержимое файла. Существуют даже низкоуровневые служебные команды (plumbing) для работы с этим хранилищем как с базой данных:
echo 'test content' | git hash-object -w --stdin
Эта архитектурная особенность породила мутное высказывание, что Git отслеживает переименование по содержимому файла. При переименовании объект «коммит» будет содержать ссылку на объект «содержимое файла», но если содержимое не изменилось, то это будет ссылка на объект, уже имеющийся в хранилище.
Когда разработчик создает коммит, Git помещает в хранилище один объект описания коммита и кучку объектов, описывающих файловую структуру и содержимое файлов. Таким образом, «коммиты» — это связанные между собой объекты Git в хранилище типа ключ-значение.
По умолчанию Git хранит содержимое файлов целиком: если мы поменяли строчку в 100-килобайтном исходнике, то в хранилище будет добавлен объект со всеми 100 килобайтами, сжатыми с помощью zlib. Чтобы репозиторий излишне не распухал, в Git предусмотрен garbage collector, который запускается при выполнении команды push, при этом объекты переупаковываются в pack-файл, который содержит разницу между исходным файлом и следующей ревизией (diff).
Но «ненужные» коммиты случаются не только при использовании команды reset. К примеру, популярная операция rebase просто копирует информацию о коммитах, оставляя в хранилище «оригинал», который никому уже не потребуется. Чтобы такие «потерянные» объекты не копились, в Git предусмотрен механизм сборки мусора — уже упомянутый выше garbage collector, автоматически вызываемый при выполнении команды push либо вызываемый вручную.
Garbage collector ищет объекты, на которые больше нет ссылок, и удаляет их из хранилища. Огромную роль при этом играет журнал операций reflog: ссылки в нем имеют ограниченный срок жизни, по умолчанию 30 дней для объекта без ссылок и 90 дней для объекта со ссылками. Garbage collector сначала удаляет из журнала reflog все ссылки с истекшим «сроком годности», а затем удаляет из хранилища объекты, на которые больше нет ссылок. Такая архитектура дает разработчику 30 дней, чтобы восстановить “ненужный” коммит, который в противном случае будет окончательно удален из репозитория по истечении этого срока.
Надеюсь, этот небольшой экскурс во внутренности Git сэкономит кому-нибудь ценное время при поиске «пропавших коммитов», на которые ссылается, к примеру, баг-трекер. Если я где-то ошибся или есть замечания — с удовольствием пообщаюсь в комментах.
This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий