2

git store 注释的方式:

  • 对于单个命名空间,Git 每次提交只存储一个注释。一个可以有多个命名空间。默认命名空间是提交。
  • .git/refs/notes/ 包含一个哈希(比如,MainHash_2),它是一个树对象。每当您创建便笺时,哈希都会更改。
  • 此树对象包含另外两个哈希值。一个到另一个树结构(例如注释树结构NOTES_2)和一个到父树对象(在创建此注释之前的 .git/refs/notes/ 中的那个,例如MainHash_1
  • 注释树结构包含每个注释的一个条目。每个条目都有两个哈希:一个用于注释内容,另一个用于指定提交。

如第三点所述,为什么要存储父级?由于此父级(其类型与第二点中提到的相同)还包含另一棵树,其中每个注释包含一个条目。

假设当前您有三个音符。MainHash_2包含 to 的散列NOTES_2,其中包含每个注释的三个条目。MainHash_1包含 to 的散列NOTES_1,其中包含两个条目(对于除现在创建的注释之外的所有剩余注释)。为什么要存储这两个条目两次等等?

4

2 回答 2

3

仅仅因为注释命名空间在 git 中并不是什么特别的东西,它们只是具有完整历史的普通分支。你可以做

git checkout notes/commits

并像处理任何其他分支一样处理您的笔记,例如,您可以这样做

git log notes/commits

查看您的笔记的提交日志。通过这种方式,您可以跟踪对笔记的所有更改。

你之前这么说:

.git/refs/notes/commits包含一个哈希(比如,MainHash_2),它是一个对象。

它不是一个对象,它是一个commit。就像在.git/refs/heads/master. 你可以检查它git cat-file -t <hash>

于 2013-06-10T09:44:37.453 回答
0

git notes提交 73f77b9, Git v1.6.6-rc0中引入。扇出
的概念是在 2010 年 2 月与 Git v1.7.1-rc0 一起引入的,提交 73f77b9以确定注释树的这一部分的最佳磁盘扇出,在..git/refs/notes/commits

' fanout' 变量的值:

  • 0:无扇出(所有笔记都直接存储在根笔记树中)
  • 1:2/38扇出
  • 2:2/2/36扇出
  • 3:2/2/2/34扇出

在 Git 2.25.2(2020 年 3 月)中,自动缩小注释树中扇出的代码有一个错误,该错误已被杀死。

请参阅Johan Herland ( )的commit dbc2747commit e1c5253 (03 Feb 2020 ) 。(由Junio C Hamano 合并 -- --提交 8833260中,2020 年 2 月 14 日)jherland
gitster

t3305:检查笔记扇出更仔细和健壮

总之,在这个补丁之前,这个测试脚本:

  • 创建许多笔记
  • 验证笔记树中的所有笔记的扇出为 1
  • 删除大部分笔记
  • 验证笔记树中的笔记现在的扇出为 0

扇出验证只发生了两次:在创建所有笔记之后,以及在删除大部分笔记之后。

此补丁通过在 _ 添加/删除注释后检查扇出来加强测试_each:我们断言从扇出 0 -> 1 的切换在添加注释时仅发生一次(并且该切换遍及整个注释树)。同样,我们断言从扇出 1 -> 0 的切换在删除音符时只发生一次。

此外,我们将移除后留下的音符数量从 50 个减少到 15 个,以确保无论外部因素如何,扇出 1 -> 0 的转换都会持续发生 (1)。

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

和:

notes.c:修复减少音符扇出时的错误

如上一次提交中所述,注释代码中扇出启发式的性质导致我们增加或减少注释扇出的确切点随被注释的对象而变化。
由于测试环境生成的对象 id 是确定性的(通过设计),t3305 生成和测试的注释总是相同的,因此我们碰巧看到从一次运行到下一次运行的扇出行为相同。

巧合的是,如果我们稍微改变测试环境(比如在我们开始 t3305 测试之前在一个不相关的分支上进行测试提交),我们不仅会看到扇出切换发生在不同的点,我们还设法触发了一个错误在笔记代码中,扇出1 -> 0开关没有在笔记树上统一应用,而是产生一个像这样的笔记树:

...
bdeafb301e44b0e4db0f738a2d2a7beefdb70b70
bff2d39b4f7122bd4c5caee3de353a774d1e632a
d3/8ec8f851adf470131178085bfbaab4b12ad2a7
e0b173960431a3e692ae929736df3c9b73a11d5b
eb3c3aede523d729990ac25c62a93eb47c21e2e3
...

当我们写出一个带有新减少的扇出的笔记树时,就会出现这个错误,并且笔记树包含未扩展的子树,由于扇出的减少,这些子树应该合并到父树中)

在内部音符 16 树结构中恰好位于偶数级别的子树(换句话说:d3上例中路径 - " " 的子树 - 在第一个半字节中是唯一的 - 即没有其他音符路径以" d")不会作为树写出的一部分进行解包。
这个错误会在后续的笔记树中重复出现,直到子树被强制解包。在 t3305 中,这只发生在d38ec8f8音符本身从树中移除时。

错误并不严重(没有信息丢失,注释代码能够读取/解码此树并正确操作它),但这仍然是当前实现中的一个错误,应该修复。

也就是说,修复一个错误并非没有复杂性:

我们必须考虑到load_subtree()调用 from for_each_note_helper()(现在在我们写出注释树时正确解包子树)可能最终将解包的非注释插入到non_notestruct 保存的条目的链接列表中notes_tree
由于我们正在写出笔记树,所以这个链表目前正在被 遍历write_each_non_note_until()
解压后的非注释必须插入到我们写出的最后一个非注释和下一个要写入的非注释之间。
因此,我们不能简单地持有next_non_noteto write in struct write_each_note_data(因为我们会默默地跳过这些新插入的注释),而是必须始终遵循->next我们写的最后一个非注释的指针。(这部分被 t3304 中的现有测试捕获。)

于 2020-02-17T17:07:22.600 回答