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
, со следующими исключениями:
При чтении переменной core.repositoryformatversion
, git
реализация, которая поддерживает версию 1, ДОЛЖНА также читать любую
ключи конфигурации находятся в разделе extensions
файл конфигурации.
Если в хранилище версии 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.preciousObjects
true
, объекты в хранилище НЕ ДОЛЖНЫ быть удалены (например, 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. После этого коммита это нормально.)