吉特:到底为什么会有这种说法;git基于文件之间的差异;错了吗?

吉特:到底为什么会有这种说法;git基于文件之间的差异;错了吗?,git,Git,我知道git add只保存特定文件的新快照。但我对“快照”这个词有点困惑。正如我对git(例如or)源代码的理解,快照实际上只是与上次提交的区别 引自: 它基本上拍摄了您的所有文件当时的样子,并存储了对该快照的引用。为了提高效率,如果文件没有更改,Git不会再次存储该文件,只是指向它已存储的上一个相同文件的链接 对我来说,这听起来很像基于文件差异的系统描述-- 编辑: 具体来说: 我理解,如果不修改blob,则哈希不会更改,因此在进一步提交中使用。对我来说,git可以检测blob之间的相似性,从

我知道git add只保存特定文件的新快照。但我对“快照”这个词有点困惑。正如我对git(例如or)源代码的理解,快照实际上只是与上次提交的区别

引自:

它基本上拍摄了您的所有文件当时的样子,并存储了对该快照的引用。为了提高效率,如果文件没有更改,Git不会再次存储该文件,只是指向它已存储的上一个相同文件的链接

对我来说,这听起来很像基于文件差异的系统描述--

编辑:

具体来说:


我理解,如果不修改blob,则哈希不会更改,因此在进一步提交中使用。对我来说,git可以检测blob之间的相似性,从而消除冗余,这也是有道理的

=>如果我将调用例如vimdiff(仅用于说明概念)到一个blob并将输出保存在一个新blob中,这是否等效


=>更改后的blob与其他blob有什么共同之处?

这取决于“基于文件之间的差异”的含义。有些系统(如hg或DARC)不存储整个文件,而只存储其版本之间的差异(补丁),因此可以通过将完整的差异历史应用到给定的提交来恢复每个版本


相反,Git将每个文件的每个版本存储为一个独立的blob,就好像它是从头创建的一样。但是,正如书中所说,如果一个文件没有更新,什么都不会被写入。

简短回答:不,Git总是记录整个文件

更长的回答:好吧,那不完全正确。从逻辑上讲,Git总是记录整个文件。但是,在存储后端,Git对所有版本的所有文件执行增量压缩,因此它甚至可以检测不同文件之间以及所有分支的整个历史记录中的相同内容,而不仅仅是父提交。而且由于网络协议和存储后端共享相同的格式(“打包文件”),因此
push
fetch
的效率是相同的

但是,请务必记住,这是存储后端的内部实现细节。它不是对象模型的一部分。对象模型是每个提交都包含整个树

这是Git的对象模型:

  • 水滴:一个副流。基本上是一个文件,但仅限于其内容。它没有名字。这样,Git就像Unix文件系统一样工作,文件没有名称,而是目录将名称与文件关联

  • 树:一个平面(!!!)的
    (模式,名称,{tree | blob})
    三元组列表。这相当于Unix目录。它将名称和模式(主要是可执行的或不可执行的)与blob或tree相关联。也就是说,树可以是递归的

  • 提交:指向树的指针和指向零、一或多个父提交的指针。还包含一个日期戳和两个名称字符串(author和committer)以及最重要的提交消息

  • (本地标记):从技术上讲,不是Git对象。只是一个指向提交的本地文件

  • 注释标记:包含指向提交、名称和注释消息的指针

  • 签名标记:包含一个带注释的标记(???)和一个数字签名[不确定这一个,是建立在带注释的标记之上还是复制它?]

  • 注意:一段可以附加到任何Git对象的文本。这可用于向任何Git对象添加任意用户定义的元数据,例如,CI服务器可以将代码覆盖率结果附加到提交,或者错误跟踪器可以将链接附加到用于修复错误的提交的票证,web服务器可以将MIME类型附加到Blob,发布管理系统可以将通过/不通过投票附加到带注释的标记


请注意,实际上只有blob包含文件数据。剩下的只是指针。blob没有名称,这意味着只要blob具有相同的内容,它就是相同的blob,因此在对象存储中只存在一次。事实上,它甚至在整个Git世界中只存在一次!例如,FSF的GPL
复制
文件,只要您保持它不被修改,即使在完全不相关的存储库中,也将是完全相同的blob

我认为那本书有误导性。提交存储指向树的指针,树存储指向blob和trees的指针,blob只是文件的内容。如果文件未更改,则blob与以前相同,并且它已在对象存储中,因此无需执行任何操作。但这并不是提交的真正功能。我已经改进了我的原始问题以解决这一困惑。树列表条目中的“平面”是什么意思?我的意思是树实际上并不存储树,而是存储指针列表。树的“深度”来源于递归定义,即允许指针指向树和blob。这并不是唯一的,这基本上是定义树数据结构的标准方法,当然也是Unix目录的工作方式,但有些人认为整个树存储在单个对象中,事实并非如此。我理解,如果不修改blob,哈希就不会更改,因此在进一步的提交中使用。这对我来说也很有意义,git可以检测blob之间的相似性,从而消除冗余如果我将vimdiff(只是为了说明概念)调用到一个blob并将输出保存到一个新blob中,这是否等效更改后的blob与其他blob有何共同之处?签名标记只是包含签名的带注释标记。此外,注释不是一种特殊的对象类型,它们只是相同的对象