【问题标题】:What is the mathematical structure that represents a Git repo代表 Git 存储库的数学结构是什么
【发布时间】:2014-11-28 13:49:58
【问题描述】:

我正在学习 Git,如果我能对代表 Git 存储库的数学结构进行描述,那就太好了。例如:它是一个有向无环图;它的节点代表提交;它的节点有标签(每个节点最多一个标签,没有标签使用两次)代表分支等。(我知道这个描述不正确,我只是想解释我在找什么。)

【问题讨论】:

标签: git graph


【解决方案1】:

除了 Nevik Rehnel 评论中的链接(根据请求复制到此处: eagain.net/articles/git-for-computer-scientistsgitolite.com/gcs) 和 sehe's point that the commit graph forms a Merkle Tree,我会添加一些注释。

  • 对象存储中有四种对象类型:commit、tree、annotated-tag 和 blob(文件)。
  • 一个提交对象只包含一个树引用(当然可以指向更多树)、一个可能为空的父 SHA-1 哈希列表(必须都是更多提交)、一个作者(姓名、电子邮件、和时间戳)、提交者(与作者的形式相同)和提交文本。
  • 树对象包含重复 0 次或多次的(模式、子对象、文件名)列表。如果子对象是另一棵树,则文件名代表一个目录。如果它是一个 blob,它代表一个文件。该模式看起来像 POSIX 文件模式,如果它是 120000(符号链接的文件模式),则文件的“内容”实际上是符号链接目标。某些模式值(ab)用于子模块,但我忘记了。不存储 R 和 W 模式位,仅存储 X 位(即使 repo 配置要求忽略它们,它们也会被忽略)。
  • annotated-tag 对象包含对象引用、标记器(名称、电子邮件和时间戳)和标记文本。引用的对象通常是一个提交,但标签对象可以指向任何对象(甚至是另一个标签对象)。
  • 标签(分支和标签以及引用日志引用等)位于对象存储之外。对于带注释的标签,外面有一个标签,指向对象存储内的带注释的标签对象。对于轻量级标签,外部标签指向提交。
  • 没有限制只有一个根提交。任何没有父母的提交都是根。
  • Git 几乎从不创建一个空树(它代表一个空目录),除了两种情况:每个 repo 中始终有一个空树,如果您进行初始空提交(使用git commit --allow-empty)它使用那棵空树。 (由于空树没有子对象,its SHA-1 hash value is a constant。)
  • “DAG”描述通常用于通过关闭提交父哈希形成的树。然而,一个树对象通常不应该包含在它的任何子树中,如果你设法创建一个循环树结构,你将无法检查它(因为它无限递归)。假设您不能创建具有相同校验和的两棵不同的树(如果您可以破坏 git),您将找不到包含树 T2 的树 T1,而树 T2 包含校验和为 T1 的不同树。因此,这些树也隐含地是一个 DAG,并且附加到提交 DAG,它们形成了一个更大的 DAG。 :-)
  • 对象存储中未引用的对象将由git gc 进行垃圾收集。空树似乎对收集免疫。 refs/logs/ 目录和文件 packed-refs 中的任何内容(在 .git 中,或用于裸存储库或设置 $GIT_DIR 时,其他任何地方)都充当参考,特殊名称(@ 987654335@、ORIG_HEAD等);我不确定其他随机文件(如果在 .git 创建并包含有效的 SHA-1)是否可以作为参考。
  • 索引有一些我从未研究过的格式。它包含对对象存储中对象的引用。当您git add 一个文件时,git 将文件放入对象存储并将(非文本)SHA-1 哈希放入索引文件中。这些是阻止垃圾回收的有效引用。

【讨论】:

  • 我认为,如果您直接包含我第一次发布的链接,它可能会对未来的读者有所帮助;)如果您知道任何来源,可能还有更多来源
  • 关于最后两个要点的两个小注释:是的,.git/refs/ 中的任何内容都将被尝试解释为 ref(logs/ 可能也是这种情况),但它们通常不会出现在任何地方(因为 git branchgit tag 指的是特定的参考子集)。其次,索引基本上是一个树对象,它将形成下一次提交的顶级树。 (虽然我不知道它的文件格式是不是和写入磁盘的树一样)
  • @NevikRehnel:索引的格式不同(与常规树对象一样)。特别是,在合并期间,它最多可以包含任何给定文件(阶段 1、2 和 3)的三个“额外”版本;并且带有文件subfile 的子目录sub 以文字sub/subfile 出现在索引中。
  • “索引有一些我从未研究过的格式”:那么你去吧:stackoverflow.com/a/4086986/6309stackoverflow.com/a/25806452/6309
【解决方案2】:

我认为最相关的答案需要包括 Git 修订树最重要的特征:加密签名(每个修订都包括父修订的哈希和提交详细信息)。

这被称为 Merkle 树:http://en.wikipedia.org/wiki/Merkle_tree


有关一些背景,请参阅较早的答案:(Git: How to treat commit so that versions of a file exist in their entirety (not just as diffs))

背景

存储 deltas 被 RCS、CVS、Subversion 和其他(SourceSafe?)普及。主要是因为该模型使传输变更集变得容易,因为它们已经是增量形式。现代 VCS-es(主要是分布式的)已经从这一点演变而来,并强调数据完整性

数据完整性

由于对象数据库的设计,git 非常健壮,可以检测快照或整个 repo 中任何位置的任何损坏的数据位。有关 Git 存储库的加密属性的更多详细信息,请参阅这篇文章:Linus talk - Git vs. data corruption?

在 techno babble 中:提交历史记录形成加密强大的默克尔树。当提示提交 (HEAD) 的 sha1 总和匹配时,它在数学上遵循

  • 树内容
  • 分支历史记录(包括所有签核和提交者/作者凭据)

是相同的。这是 git(以及其他共享此设计功能的 SCM)的一个巨大的安全功能

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-10
    • 2016-05-29
    • 1970-01-01
    • 2021-02-26
    • 2021-03-17
    • 2012-09-02
    • 2011-06-15
    • 2016-12-15
    相关资源
    最近更新 更多