git中的`Commit hash`、`Parent Hash`和`Tree hash`有什么区别?

Zen*_*Zen 20 git

今天我通过在线阅读这个文档来学习一些基本的 git 知识:

http://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-Hi

在那一章,我开始学习使用我喜欢的git log --pretty=format:" "方式显示日志信息。

但是有些方法,我在格式表中看到了两个类似的选项,%Hfor Commit Hash%PforParent Hash%Tfor Tree Hash

我在命令行上对它们进行了试验,结果它们都是具有不同值的相同长度的哈希值。

我用谷歌搜索和计算器溢出,到目前为止没有明显的提示。

我对此有想法Hash value,它是该 git commit 的校验和。

但是做什么Parent HashTree hash做什么?

  • PS:啊,我现在有了一些想法,Parent Hash意思是分支直接起源的哈希值吗?

lin*_*jie 10

父哈希:

$ git log --graph
*   commit c06c4c912dbd9ee377d14ec8ebe2847cf1a3ec7e
|\  Merge: 79e6924 3113760
| | Author: linjie <linjielig@gmail.com>
| | Date:   Mon Mar 14 16:02:09 2016 +0800
| |
| |     commit5
| |
| |     Merge branch 'dev'
| |
| * commit 31137606f85d8960fa1640d0881682a081ffa9d0
| | Author: linjie <linjielig@gmail.com>
| | Date:   Mon Mar 14 16:01:26 2016 +0800
| |
| |     commit3
| |
* | commit 79e69240ccd218d49d78a72f33002fd6bc62f407
|/  Author: linjie <linjielig@gmail.com>
|   Date:   Mon Mar 14 16:01:59 2016 +0800
|
|       commit4
|
* commit 7fd4e3fdddb89858d925a89767ec62985ba07f3d
| Author: linjie <linjielig@gmail.com>
| Date:   Mon Mar 14 16:01:00 2016 +0800
|
|     commit2
|
* commit 316dd3fb3c7b501bc9974676adcf558a18508dd4
  Author: linjie <linjielig@gmail.com>
  Date:   Mon Mar 14 16:00:34 2016 +0800

     commit1

$ git log --pretty=format:'%<(82)%P %s'
79e69240ccd218d49d78a72f33002fd6bc62f407 31137606f85d8960fa1640d0881682a081ffa9d0  commit5
7fd4e3fdddb89858d925a89767ec62985ba07f3d                                           commit4
7fd4e3fdddb89858d925a89767ec62985ba07f3d                                           commit3
316dd3fb3c7b501bc9974676adcf558a18508dd4                                           commit2
                                                                                   commit1
Run Code Online (Sandbox Code Playgroud)

你可以看到commit4commit3是父commit5commit2是父commit3commit4commit1是父commit2

树哈希:

$ git log --pretty=format:'%T %s'
f3c7cee96f33938631a9b023ccf5d8743b00db0e commit5
e0ecb42ae45ddc91c947289f928ea5085c70b208 commit4
d466aea17dc07516c449c58a73b2dc3faa9d11a1 commit3
b39f2e707050e0c5bbb3b48680f416ef05b179ba commit2
5706ec2b32605e27fa04cbef37d582325d14dda9 commit1

$ git cat-file -p f3c7ce
100644 blob 8bb2e871e94c486a867f5cfcbc6f30d004f6a9e5    dev
100644 blob 47f16c8e00adba77ec5c176876e99c8e9f05d69b    master

$ git cat-file -p 5706ec
100644 blob fc0bfde0d44bb4d6c7d27b6e587ebedd34ba5911    master
Run Code Online (Sandbox Code Playgroud)

该命令的功能:<object>根据其类型漂亮地打印内容。

git cat-file -p 
Run Code Online (Sandbox Code Playgroud)

在 git 中,所有内容都存储为树和 blob 对象,树对应于 UNIX 目录条目,而 blob 或多或少对应于 inode 或文件内容。单个树对象包含一个或多个树条目,每个条目都包含一个指向 blob 或子树的 SHA-1 指针及其关联的模式、类型和文件名。Git 通常通过获取暂存区或索引的状态并从中写入一系列树对象来创建树。提交对象具有有关谁保存了树对象、保存时间或保存原因的信息。这是提交对象为您存储的基本信息。

结论:

提交哈希、父哈希、树哈希都是 SHA-1。提交哈希和父哈希是相同的,除了父哈希有子哈希。Tree hash 代表一个 Tree 对象。提交哈希和父哈希代表一个提交对象。

参考:

  1. Git 内部 - Git 对象

  2. git-cat-file - 提供存储库对象的内容或类型和大小信息


use*_*445 7

棵树的文件和目录,不依赖于历史上任何特定点的分层集合。例如,如果您创建一个文件,然后稍后删除该文件(没有其他干预提交),您将得到与您开始时相同的树。

一个承诺是在项目的历史上的一个点。提交指定一棵树,但也包含其他信息,例如作者/提交者和时间、提交消息(作者在其中描述更改的内容)以及最重要的零个或多个父项,即存储库的先前状态。(您的第一个提交有零个父项。此后的大多数提交在线性开发期间都有一个父项,如果合并则不止一个。)

您可以了解它是如何与git cat-file -p命令一起工作的,该命令打印特定散列的内容,而不管类型如何。例如,要查看 HEAD 提交,您可以运行:

$ git cat-file -p HEAD
tree 81ca1cb660ea79131336944df28b13b711d93557
parent 92b6b8fe9956866ace5397e060e7cc8ee1c76233
parent 7ea2575ed96d150ee19f70edea4bd42c7c2f0b83
author Mislav MarohniÄ <mislav.marohnic@gmail.com> 1436468108 -0700
committer Mislav MarohniÄ <mislav.marohnic@gmail.com> 1436468108 -0700

Merge pull request #951 from github/global-args

Avoid depending on a hardcoded list of git global flags
Run Code Online (Sandbox Code Playgroud)

要查看该提交中cat-file -p的树,您可以将其设为树:

$ git cat-file -p 81ca1cb660ea79131336944df28b13b711d93557
100644 blob 730f77a3be502cfe6769c1305c0b59c22274caf5        .gitignore
100644 blob bcbd000f6b9ad5b0510f804ac4a3b19306b39c03        .travis.yml
100644 blob da71aa1fa3c3ae47b2fe5e6245ce2eea1586e278        CONTRIBUTING.md
...
Run Code Online (Sandbox Code Playgroud)

同样,如果您查看父项,您也会看到这些都是提交。提交中树的简写,例如revis rev^{tree}。所以前面的命令可能已经写好了git cat-file -p HEAD^{tree}。请注意,rev^代表 的父级rev。当有多个父项时rev^1rev^2, 等。git rev-parse 手册页中提供了更多信息。


Bra*_*iam 3

“提交哈希”是当前提交的哈希。与条目关联的提交。

“父哈希”是提交来自的任何父分支的哈希。

“树哈希”是提交中当前目录的哈希。如果从带有 的父目录查看,该哈希值等于该目录的哈希值git ls-files --stage --abbrev

参考: