Каковы разные версии формата репозитория (для параметра core.repositoryFormatVersion) в git? - PullRequest
16 голосов
/ 03 марта 2011

Я заметил опцию по умолчанию в git core.repositoryFormatVersion, которая по умолчанию равна 0, но что такое «версии формата репозитория» и какую функциональную разницу они делают?

Ответы [ 2 ]

28 голосов
/ 03 марта 2011

Это для будущей совместимости - если разработчики git когда-либо сочтут необходимым изменить способ хранения репозиториев на диске, чтобы включить какую-то новую функцию, то они могут сделать обновленные репозитории core.repositoryformatversion из 1. Тогда более новые версии git, которые знают об этом новом формате, будут запускать код, чтобы справиться с ним, и более старые версии git, которые не будут корректно работать с "Expected git repo version <= 0, found 1. Please upgrade Git".

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

12 голосов
/ 01 ноября 2015

git 2.7 (ноябрь 2015) добавляет гораздо больше информации в новый Documentation/technical/repository-version.txt.
См. коммит 067fbd4 , коммит 00a09d5 (23 июня 2015 г.) от Джефф Кинг (peff) .
(Объединено с Junio ​​C Hamano - gitster - в коммит fa46579 , 26 октября 2015 г.)

Теперь вы можете определять «расширения» и использовать core.repositoryformatversion в качестве «маркера», чтобы сигнализировать о существовании указанных расширений, вместо того, чтобы изменять сам номер версии Git:

Если бы нам пришлось увеличивать версию хранилища для каждого такого изменения, то любая версия, понимающая реализацию X, также должна понимать X-1, X-2 и т. Д., Даже если несовместимости могут быть в ортогональных частях системы, и в противном случае нет причин, по которым мы не можем реализовать одно без другого (или, что более важно, чтобы пользователь не мог выбрать использование одной функции без другой, взвешивая компромисс в совместимости только для этой конкретной функции).

Этот патч документирует существующую стратегию repositoryformatversion и вводит новый формат "1", который позволяет хранилищу указывать, что он должен работать с произвольным набором расширений .

Выдержки из документа:

Каждый репозиторий git помечен цифровой версией в core.repositoryformatversion ключ его config файла. Эта версия определяет правила работы с данными хранилища на диске.

Обратите внимание, что это относится только к доступу к содержимому диска репозитория непосредственно.
Более старый клиент, который понимает только формат 0, может по-прежнему подключаться через git:// к репозиторию, используя формат 1, если процесс сервера понимает формат 1.

Версия 0

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

Версия 1

Этот формат идентичен версии 0, со следующими исключениями:

  1. При чтении переменной core.repositoryformatversion, git реализация, которая поддерживает версию 1, ДОЛЖНА также читать любую ключи конфигурации находятся в разделе extensions файл конфигурации.

  2. Если в хранилище версии 1 указаны extensions.* ключи, которые запущенный git не реализован, операция НЕ ДОЛЖНА продолжить. Аналогично, если значение любого известного ключа не понято при реализации операция НЕ ДОЛЖНА выполняться.

Это можно использовать, например:

  • , чтобы сообщить Git, что объекты не должны быть сокращены на основе только на досягаемости ссылок советы (например, потому что это имеет детей-клонов)

  • что ссылки хранятся в формате помимо обычного Каталоги "refs" и "pack-refs"

Теперь это действительно оригинальный подход ко всей политике номеров версий и политике semver .

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

Например, если пользователь решит использовать хранилище базы данных для ссылок, он может установить конфигурацию "extensions.refbackend" в "db".
Старые версии git не понимают формат "1" и залог.
Версии git, которые понимают «1», но не знают о «refbackend», или которые знают о «refbackend», но не знают о «db» backend, откажутся работать.
Это, конечно, раздражает, но гораздо лучше, чем альтернатива утверждать, что в репозитории нет ссылок, или писать в местоположение, которое другие реализации не будут читать.

Обратите внимание, что здесь мы определяем только правила для формата 1.
Мы сами никогда не пишем формат 1; это инструмент, предназначенный для использования пользователями и будущими расширениями для обеспечения безопасности при более старых реализациях .


В качестве первого расширения у вас будет git2.7 preciousObjects:

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

В документе упоминается:

Когда установлен ключ конфигурации extensions.preciousObjectstrue, объекты в хранилище НЕ ДОЛЖНЫ быть удалены (например, git-prune или git repack -d).

То есть:

Например,если вы сделаете:

$ git clone -s parent child
$ git -C parent config extensions.preciousObjects true
$ git -C parent config core.repositoryformatversion 1

, теперь у вас есть дополнительная безопасность при запуске git в родительском репозитории.
Черносливы и перепаковки выдаст ошибку, и git gc пропуститэти операции (он будет продолжать упаковывать ссылки и выполнять другие необъектные операции).
Старые версии git при запуске в хранилище не будут работать при каждой операции.

Обратите внимание, что мы не устанавливаемрасширение preciousObjects по умолчанию при выполнении «clone -s», так как это нарушает обратную совместимость.Это решение, которое пользователь должен принять явно.


Обратите внимание, что это core.repositoryformatversion дело старое.Действительно старый. commit ab9cb76, ноябрь 2005 г., Git 0.99.9l .
Первоначально было сделано для версии базы данных :

Это составляет init-dbизвестна версия репозитория.

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


Git 2.22 (Q22019) позволит избежать утечек вокруг структуры repository_format.

См. commit e8805af (28 февраля 2019) и commit 1301997 (22 января 2019) к Мартин Агрен (``) .
(Объединено Junio ​​C Hamano - gitster - в коммит 6b5688b , 20 марта 2019 г.)

setup: исправить утечки памяти с помощью struct repository_format

После того, как мы настроили struct repository_format, он владеет различными частями выделенной памяти.Затем мы либо используем эти члены, потому что решили, что хотим использовать формат репозитория «кандидат», либо отбрасываем пространство кандидатов / пустых мест.
В первом случае мы передаем владение памятью нескольким глобальным переменным.В последнем случае мы просто молча отбрасываем структуру и заканчиваем утечкой памяти.

Ввести макрос инициализации REPOSITORY_FORMAT_INIT и функцию clear_repository_format(), которые будут использоваться на каждой стороне read_repository_format().Чтобы иметь ясное и простое владение памятью, пусть все пользователи struct repository_format дублируют строки, которые они берут из нее, а не крадут указатели.

Вызовите clear_...() в начале read_...() вместопросто обнуление структуры, так как мы иногда вводим функцию несколько раз.
Таким образом, важно инициализировать структуру перед вызовом read_...(), поэтому задокументируйте это.
Это также важно, потому что мы можем даже не вызывать read_...() прежде чем мы вызовем clear_...(), см., например, builtin/init-db.c.

Научите read_...() очистить структуру при ошибке, чтобы она была сброшена в безопасное состояние, и задокументировать это.(В setup_git_directory_gently() мы смотрим на repo_fmt.hash_algo, даже если repo_fmt.version равен -1, что мы не должны были делать по API. После этого коммита это нормально.)

...