Git中的“树”是什么意思?

4

名称

git-diff - 显示提交之间、提交和工作树之间的更改等

描述

显示工作树和索引或之间的更改,索引和之间的更改, 两个之间的更改,两个blob对象之间的更改,或磁盘上两个文件之间的更改。

"工作树"是否指的是工作目录?

这里的"a tree"是什么意思?它与提交对象或树对象相同吗?(字面上来说,我认为它指的是树对象。但我想可能是通过将“DESCRIPTION”部分与“NAME”部分进行比较,意图是指提交对象。)

如何将"a tree"指定为git diff命令的参数?

如果可以问一下,如何将“blob对象”指定为git diff命令的参数?


1
可能是工作树 vs 工作目录的重复问题。 - user3942918
2个回答

7

Tree这个词在Git中(以及计算机领域)有点多义。

工作目录工作树(或其他拼写变体)是指您进行工作的位置。在此处,文件具有正常的日常形式,并且可以读取和(如果操作系统允许)写入。 (在Unix系统上,如果您使用chmod -w更改文件,您将无法编写它们。但那不是Git的错。)

在Git中,树对象是一种内部数据结构,记录目录树或子树。它包含每个文件或子目录的一个条目(对于子模块,则为该子模块的gitlink条目)。每个条目列出文件的可执行模式位,作为奇怪编码的yes或no标志,以及文件的名称和blob哈希ID。对于子树,条目列出目录的名称和子目录对象哈希ID。 Git随后可以递归地通过子树对象来查找更多文件和更多子树(如有需要)。每个文件条目都为Git内部blob对象提供哈希ID,该对象是文件数据的冻结(只读)压缩副本。

每次提交保存一个(1)内部Git树对象哈希ID。该树对象包含提交包含的快照--因此提交的快照实际上是这些树之一,其中包含文件和子树的条目。由于每个提交都有一个树,Git可以从提交说明符转换为树对象:

$ git rev-parse master
3c31a203fbeedb4d746889dc77cbafc395fc6e92
$ git rev-parse master^{tree}
5c4b695f5d5606976f5b72e1a901ed17db30a359

在这种情况下,由master标识的commit是第一个丑陋的哈希值,但是此提交所使用的内部tree对象用于保存文件的是第二个。
因此,工作树(work-tree)包含具有实际数据的实际文件,Git tree对象(tree object)允许Git找到某个提交对应的所有冻结文件,只要您提供相应的树对象。 git diff命令需要比较两个项目。这两件事可以是两个单独的文件,也可以是两个文件树。无论它们是树对象还是工作树中充满文件,git diff都会:
- 比较每棵树中的文件名称。 - 如果文件名匹配,Git假定这些是“相同的文件”,并将比较文件内容。 - 如果它们没有匹配的名称,则可选择通过内容匹配来匹配文件。 - 如果其他所有方法都失败,则告诉您删除了某些文件并添加了某些文件。删除文件的内容全部删除;添加文件的内容全部是新的。
这仅是概述,因为git diff可以做更多的事情,但这些就是基础知识。
还有一个非常重要的细节: git diff会检查索引并将其视为树。 索引包含从某处复制的文件副本。 最初,某处是您git checkout的任何提交。 但是,您可以使用git add命令从工作树中添加文件以将它们复制到索引中,替换在提交中存储的版本。 您可以从未提交过的工作树中使用git add命令添加文件,因此对索引来说是新的。 此外,您可以使用git rm命令,带有或不带有--cached选项,将文件从索引中删除。
由于Git将从运行git commit时索引中的内容构建一个提交,因此将索引内容与某些冻结树或工作树进行比较是一件非常有用的事情。

1实际的树形条目存储(模式,路径,哈希)三元组。 mode 是一个字符串:对于可执行文件,是 100755;对于非可执行文件,是 100644;对于子树,是 40000;对于符号链接,是 120000;对于 git 链接,是 160000。这些最初是 Linux 的 stat st_mode 字段,Git 允许使用例如 rw-rw-r-- 所表示的 100664,但那被证明是一个错误,因此普通的树只使用有限的子集中的一个。Git 仍然支持 100664,因为可能还有一些 Git 存储库仍具有这样的条目,但除非你找到一个非常旧的存储库,否则不会找到任何 100664。哈希始终是 blob 哈希值,除了 gitlink 条目,其中哈希是子模块中所需的提交哈希。


1
当前工作目录是您的shell认为它在哪里。 当前工作树从带有.git repos的目录开始。如果它说工作目录,您可能会认为它会随着您的移动而移动-但实际上并不会。
就参考git仓库中的树而言,我在文档中没有看到这个术语; 我记得只看到过工作树。
但是为了完成您所询问的任务,我通常使用特定提交的日志行中的签名。 如果是当前提交,则使用“HEAD”或您的分支名称都可以。 如果是不同分支的头文件,则命名该分支即可。 如果已标记,则标记名称有效。 还有HEAD ^ 1表示上一个提交。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接