git 中都有哪些不同的存储库格式版本(对于 core.repositoryFormatVersion 设置)?
Posted
技术标签:
【中文标题】git 中都有哪些不同的存储库格式版本(对于 core.repositoryFormatVersion 设置)?【英文标题】:what are the different repository format versions (for the core.repositoryFormatVersion setting) in git?git 中有哪些不同的存储库格式版本(对于 core.repositoryFormatVersion 设置)? 【发布时间】:2011-07-07 16:59:29 【问题描述】:我注意到 git core.repositoryFormatVersion
中有一个默认选项默认为 0,但什么是“存储库格式版本”以及它们有什么功能差异?
【问题讨论】:
四年半后,Git 2.7(2015 年 11 月)终于记录了core.repositoryFormatVersion
,这真是……非常有趣。见my answer below
【参考方案1】:
git 2.7(2015 年 11 月)在新的 Documentation/technical/repository-version.txt
中添加了更多信息。
参见commit 067fbd4、commit 00a09d5(2015 年 6 月 23 日)Jeff King (peff
)。(由 Junio C Hamano -- gitster
-- 合并于 commit fa46579,2015 年 10 月 26 日)
您现在可以定义“扩展”,并使用core.repositoryformatversion
作为“标记”来表示所述扩展的存在,而不必自己增加 Git 版本号:
如果我们要针对每个此类更改增加存储库版本,那么任何实现理解版本
X
也必须理解X-1
、X-2
等等,即使不兼容性可能在正交部分中系统,否则我们没有理由不能 实现一个而没有另一个(或者更重要的是,用户不能选择使用一个功能而没有另一个,权衡仅针对该特定功能的兼容性权衡)。
此补丁记录了现有的
repositoryformatversion
策略并引入了一种新格式“1”,它允许存储库指定它必须使用任意扩展集运行。
文档摘录:
每个 git 存储库在
core.repositoryformatversion
其config
文件的键。这个版本 指定对磁盘存储库数据进行操作的规则。
请注意,这仅适用于访问存储库的磁盘内容 直接。 只要服务器进程理解格式
1
,旧客户端仍可以通过git://
连接到使用格式1
的存储库。
版本
0
这是git初始版本定义的格式,包括但不限于repository目录、repository配置文件、object和ref存储的格式。
版本
1
此格式与版本
0
相同,但有以下例外:
读取
core.repositoryformatversion
变量时,git 支持版本 1 的实现还必须阅读任何 在extensions
部分中找到的配置键 配置文件。
如果版本 1 存储库指定任何
extensions.*
密钥 正在运行的 git 尚未实现,该操作不得 继续。同样,如果任何已知键的值不被理解 通过实施,操作不得继续。
这个可以用,例如:
通知 git 对象不应基于修剪 仅在参考提示的可达性上(例如,因为它 有“克隆 --shared”孩子)
refs 以不同于通常的格式存储 “refs”和“packed-refs”目录
现在这确实是所有release version number policy 及其semver policy 的原始方法。
因为我们碰到了格式“1”,并且因为格式“1”要求正在运行的 git 知道提到的任何扩展,所以我们知道旧版本的代码在遇到这些新格式时不会做任何危险的事情。
例如,如果用户选择使用数据库存储 refs,他们可以将“extensions.refbackend”配置设置为“db”。 旧版本的 git 无法理解格式“1”和保释。 理解“1”但不知道“refbackend”或知道“refbackend”但不知道“db”后端的 git 版本将拒绝运行。 当然,这很烦人,但比声称存储库中没有引用或写入其他实现不会读取的位置的替代方法要好得多。
请注意,我们在这里只定义格式 1 的规则。 我们自己从来不写格式 1; 它是一种供用户和未来扩展使用的工具,旨在为旧实现提供安全性。
作为第一个扩展,您将拥有 git 2.7 preciousObjects
:
如果在存储库中使用此扩展,则不应运行任何可能从对象存储中删除对象的操作。如果您与其他您看不到 refs 的存储库共享该存储,这将很有用。
文档提到:
当配置键
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 在存储库中运行时,每次操作都会失败。
请注意,在执行“
clone -s
”时,默认情况下我们不会设置preciousObjects
扩展名,因为这样做会破坏向后兼容性。这是用户应该明确做出的决定。
请注意,此 core.repositoryformatversion
业务已过时。真的老了。 commit ab9cb76, Nov. 2005, Git 0.99.9l.
是done initially for the db version:
这使
init-db
知道存储库版本。
它检查现有配置文件是否表明正在重新初始化的存储库版本错误并在造成进一步伤害之前中止。
Git 2.22(2019 年第二季度)将避免在
repository_format
结构。
参见commit e8805af(2019 年 2 月 28 日)和 commit 1301997(2019 年 1 月 22 日)Martin Ågren (``)。(由 Junio C Hamano -- gitster
-- 合并于 commit 6b5688b,2019 年 3 月 20 日)支持>
setup
:使用struct repository_format
修复内存泄漏
我们设置
struct repository_format
后,它拥有各种 分配的内存。然后我们要么使用这些成员,因为我们决定我们 想要使用“候选”存储库格式,或者我们丢弃 候选/暂存空间。 在第一种情况下,我们将内存的所有权转移给几个全局变量。在后一种情况下,我们只是默默地删除结构并最终导致内存泄漏。
引入一个初始化宏
REPOSITORY_FORMAT_INIT
和一个 函数clear_repository_format()
,用于read_repository_format()
。要拥有清晰简单的内存所有权, 让struct repository_format
的所有用户复制 他们从中获取,而不是窃取指针。
在
read_...()
的开头调用clear_...()
而不仅仅是归零 结构体,因为我们有时会多次输入函数。 因此,在调用read_...()
之前初始化结构很重要,所以 记录下来。 这也很重要,因为我们甚至可能不会在调用clear_...()
之前调用read_...()
,例如,请参阅builtin/init-db.c
。
教导
read_...()
清除错误的结构,使其重置为 一个安全的状态,并记录下来。 (在setup_git_directory_gently()
,我们 看看repo_fmt.hash_algo
即使repo_fmt.version
是-1,我们 实际上不应该按照 API 执行。在这个提交之后,那就是 好的。)
使用 Git 2.28(2020 年第三季度),运行时本身可以自动升级存储库格式版本,例如在非浅层提取时。
参见Xin Li (livid
)commit 14c7fa2、commit 98564d8、commit 01bbbbd、commit 16af5f1(2020 年 6 月 5 日)。(由 Junio C Hamano -- gitster
-- 合并到 commit 1033b98,2020 年 6 月 29 日)
fetch
: 允许在初始克隆后添加过滤器签字人:李鑫
追溯添加过滤器对于现有的浅克隆很有用,因为它们允许用户查看早期更改历史记录,而无需在常规
--unshallow
fetch 中下载所有 git 对象。如果没有此补丁,用户可以通过编辑存储库配置来将远程克隆转换为承诺者,例如:
git config core.repositoryFormatVersion 1 git config extensions.partialClone origin git fetch --unshallow --filter=blob:none origin
由于完成这项工作的困难部分已经到位并且此类编辑可能容易出错,因此请教 Git 自动执行所需的配置更改。
请注意,此更改不会修改现有的 Git 行为,即识别设置
extensions.partialClone
而无需更改repositoryFormatVersion
。
警告:在 2.28-rc0 中,我们更正了一个错误,即即使在版本 0 的存储库中,某些存储库扩展也会被错误地接受(extensions.*
命名空间中的这些配置变量应该在版本号为 1 的存储库中具有特殊含义或更高),但这有点太大了。
参见Jonathan Nieder (artagnon
)commit 62f2eca、commit 1166419(2020 年 7 月 15 日)。(由 Junio C Hamano -- gitster
-- 合并于 commit d13b7f2,2020 年 7 月 16 日)
Revert "check_repository_format_gently()
: 拒绝旧仓库的扩展”报告人:Johannes Schindelin签字人:Jonathan Nieder
这将恢复commit 14c7fa269e42df4133edd9ae7763b678ed6594cd。
core.repositoryFormatVersion
字段是在ab9cb76f661(“存储库格式版本检查。”,2005-11-25,Git v0.99.9l -- merge)中引入的,提供了受欢迎的前向兼容性,谢谢Martin Atukunda 的一些受欢迎的分析。语义很简单:
core.repositoryFormatVersion
设置为 0 的存储库应该可以被所有正在使用的 Git 实现所理解;并且 Git 实现应该尽早出错,而不是尝试对具有更高core.repositoryFormatVersion
值的 Git 存储库采取行动,这些值代表他们不理解的新格式。直到00a09d57eb8 才需要定义新的存储库格式(引入
core.repositoryformatversion
的“扩展”形式,2015-06-23)。这为 Git 存储库提供了更细粒度的扩展机制。
在将
core.repositoryFormatVersion
设置为 1 的存储库中,Git 实现可以对修改存储库解释方式的“扩展。*”设置进行操作。在存储库格式版本 1 中,无法识别的扩展设置会导致 Git 出错。
如果用户设置了扩展设置但忘记将存储库格式版本增加到 1,会发生什么情况? 在这种情况下,扩展设置仍然可以识别;更糟糕的是,无法识别的扩展设置不会导致 Git 出错。
因此,将存储库格式版本 0 与扩展设置相结合在某种意义上会产生两全其美的结果。
为了改善这种情况,因为 14c7fa269e4
(check_repository_format_gently()
: 拒绝旧存储库的扩展,2020-06-05)Git 会忽略 v0 模式下的扩展。通过这种方式,v0 存储库可以获得历史(2015 年之前)行为,并保持与不了解 v1 格式的 Git 实现的兼容性。不幸的是,用户一直在使用这种配置,这种行为变化让很多人感到意外:
“git config --worktree”的用户已按照其建议启用 extensions.worktreeConfig(同时不增加存储库格式版本)会发现他们的工作树配置不再生效 copybara[*] 等工具在现有存储库中设置了 extensions.partialClone(未同时增加存储库格式版本)会发现该设置不再生效如果我们回到 2015 年,14c7fa269e4 中引入的行为可能是一个很好的行为,但我们为时已晚。
出于某种原因,我认为这是最初实施的,并且已经退步了。
很抱歉,在 14c7fa269e4 正在开发中时没有做我的研究。
让我们回到自 2015 年以来的行为:始终对扩展进行操作。* 设置,无论存储库格式版本如何。
在这里,包括一些测试来描述对“升级存储库版本”代码路径的影响。
[*]https://github.com/google/copybara/commit/ca76c0b1e13c4e36448d12c2aba4a5d9d98fb6e7
【讨论】:
【参考方案2】:这是为了未来的兼容性——如果 git 开发人员发现有必要更改存储库在磁盘上的存储方式以启用某些新功能,那么他们可以使升级后的存储库具有 core.repositoryformatversion
或 1
。然后知道新格式的新版本 git 将触发代码来处理它,而旧版本的 git 不会优雅地出现 "Expected git repo version <= 0, found 1. Please upgrade Git"
错误。
到目前为止,唯一定义或识别的 repo 格式版本是0
,它表示每个公开版本的 git 都使用的格式。
【讨论】:
请注意,Git 2.7(2015 年 11 月,四年半后)最终记录了core.repositoryFormatVersion
。见my answer below以上是关于git 中都有哪些不同的存储库格式版本(对于 core.repositoryFormatVersion 设置)?的主要内容,如果未能解决你的问题,请参考以下文章