为什么父项存储在git notes中?

为什么父项存储在git notes中?,git,git-svn,internals,git-notes,Git,Git Svn,Internals,Git Notes,git store注意到: Git对于单个名称空间每次提交只存储一个注释。一个可以有多个名称空间。默认名称空间是commit .git/refs/notes/包含一个哈希(例如,MainHash_2),它是一个树对象。无论何时创建便笺,哈希都会更改 此树对象还包含两个哈希。一个到另一个树结构(notes树结构,例如notes_2)和一个到父树对象(创建此备注之前的.git/refs/notes/中的一个,例如MainHash_1) 注释树结构包含每个注释的一个条目。每个条目有两个散列:一个用于

git store注意到:

  • Git对于单个名称空间每次提交只存储一个注释。一个可以有多个名称空间。默认名称空间是commit
  • .git/refs/notes/包含一个哈希(例如,
    MainHash_2
    ),它是一个树对象。无论何时创建便笺,哈希都会更改
  • 此树对象还包含两个哈希。一个到另一个树结构(notes树结构,例如
    notes_2
    )和一个到父树对象(创建此备注之前的.git/refs/notes/中的一个,例如
    MainHash_1
  • 注释树结构包含每个注释的一个条目。每个条目有两个散列:一个用于记录内容,另一个用于指定提交
如第三点所述,为什么要存储父级?由于此父级(其类型与第二点中提到的相同)还包含另一个树,每个注释包含一个条目


假设你现在有三个音符
MainHash_2
包含到
NOTES_2
的散列,每个note包含三个条目
MainHash_1
包含一个到
NOTES_1
的散列,其中包含两个条目(对于除现在创建的注释外的所有其余注释)为什么要将这两个条目存储两次,以此类推???

因为notes名称空间在git中不是什么特别的东西,它们只是具有完整历史记录的普通分支。你能行

git checkout notes/commits
并像处理任何其他分支一样处理您的笔记,例如,您可以

git log notes/commits
查看笔记的提交日志。这样,您就可以跟踪笔记的所有更改

你说:

.git/refs/notes/commits
包含一个散列(例如,
MainHash_2
),它是一个树对象

它不是树对象,而是提交。就像在
.git/refs/heads/master中一样。您可以使用git cat文件检查它-t

是在中引入的。
2010年2月,Git v1.7.1-rc0引入了扇出的概念,在
.Git/refs/notes/commits
中确定了notes树这一部分的最佳磁盘扇出

fanout
”变量的值:

  • 0
    :无扇出(所有注释直接存储在根注释树中)
  • 1
    2/38
    fanout
  • 2
    2/2/36
    fanout
  • 3
    2/2/2/34
    fanout
在Git2.25.2(2020年3月)中,notes树中自动缩小扇出的代码出现了一个关闭一个的bug,这个bug已经被杀死

参见(2020年2月3日)作者。
(于2020年2月14日合并)

:更仔细、更稳健地检查注释扇出 简而言之,在此修补程序之前,此测试脚本:

  • 创建许多注释
  • 验证notes树中的所有notes的扇出值是否为1
  • 删除大多数注释
  • 验证notes树中的notes现在是否具有0的扇出
扇出验证只发生了两次:创建所有注释后,以及删除大部分注释后

此修补程序通过在添加/删除注释后检查fanout来增强测试:我们断言,在添加注释时,fanout 0->1的切换只发生一次(并且该切换贯穿整个注释树)。同样,我们断言,从扇出1->0的切换在删除注释时只发生一次

此外,我们将删除后留下的注释数量从50个减少到15个,以确保扇出1->0转换在不考虑外部因素的情况下继续发生(1)

(1) :当前(使用SHA1散列函数和测试环境的确定性对象ID)notes代码中的扇出启发式恰好在109个notes处从0->1切换,在59个notes处从1->0切换
但是,更改哈希函数或其他外部因素会改变这些数字,理论上,后者可能会低至15。
有关更多详细信息,请参阅

以及:

:在减少注释扇出时修复一个错误 如前一次提交中所述,notes代码中扇出启发式的性质导致我们增加或减少notes扇出的确切点随注释对象的不同而变化。
由于测试环境生成的对象ID是确定性的(根据设计),t3305生成和测试的注释总是相同的,因此我们在一次运行到下一次运行时碰巧看到相同的扇出行为

巧合的是,如果我们稍微改变一下测试环境(比如在开始t3305测试之前在一个不相关的分支上进行测试提交),我们不仅看到扇出开关在不同的点上发生,我们还设法在notes代码中触发一个bug,其中fanout
1->0
开关未在notes树中统一应用,而是生成如下notes树:

...
bdeafb301e44b0e4db0f738a2d2a7beefdb70b70
bff2d39b4f7122bd4c5caee3de353a774d1e632a
d3/8ec8f851adf470131178085bfbaab4b12ad2a7
e0b173960431a3e692ae929736df3c9b73a11d5b
eb3c3aede523d729990ac25c62a93eb47c21e2e3
...
当我们使用新减少的扇出写入notes树时,会发生此错误,并且notes树包含未扩展的子树,这些子树应由于扇出减少而合并到父树中)

恰好位于内部notes 16树结构中偶数级别的子树(换句话说:其路径-“
d3
”在上例中-在第一个半字节中是唯一的-即,没有其他以“
d
”开头的注释路径)不会作为树写出的一部分进行解压缩。
此错误将在随后的注释树中重复,直到子树被强制解包。在t3305中,只有当
d38ec8f8
注释本身从树中删除时,才会发生这种情况

错误并不严重(没有信息丢失,notes代码能够读取/解码此树并正确操作),但这仍然是c语言中的一个错误