git hash 是如何计算的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35430584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How is the git hash calculated?
提问by The user with no hat
I'm trying to understand how git calculates the hash of refs.
我试图了解 git 如何计算 refs 的哈希值。
$ git ls-remote https://github.com/git/git
....
29932f3915935d773dc8d52c292cadd81c81071d refs/tags/v2.4.2
9eabf5b536662000f79978c4d1b6e4eff5c8d785 refs/tags/v2.4.2^{}
....
Clone the repo locally. Check the refs/tags/v2.4.2^{}
ref by sha
在本地克隆 repo。检查refs/tags/v2.4.2^{}
sha的ref
$ git cat-file -p 9eabf5b536662000f79978c4d1b6e4eff5c8d785
tree 655a20f99af32926cbf6d8fab092506ddd70e49c
parent df08eb357dd7f432c3dcbe0ef4b3212a38b4aeff
author Junio C Hamano <[email protected]> 1432673399 -0700
committer Junio C Hamano <[email protected]> 1432673399 -0700
Git 2.4.2
Signed-off-by: Junio C Hamano <[email protected]>
Copy the decompressed content so that we can hash it.(AFAIK git uses the uncompressed version when it's hashing)
复制解压缩的内容,以便我们可以对它进行散列。(AFAIK git 在散列时使用未压缩的版本)
git cat-file -p 9eabf5b536662000f79978c4d1b6e4eff5c8d785 > fi
Let's SHA-1 the content using git's own hash command
让我们使用 git 自己的 hash 命令对内容进行 SHA-1
git hash-object fi
3cf741bbdbcdeed65e5371912742e854a035e665
Why the output is not [9e]abf5b536662000f79978c4d1b6e4eff5c8d785
? I understand the first two characters (9e
) is the length in hex. How should I hash the content of fi
so that I can get the git ref abf5b536662000f79978c4d1b6e4eff5c8d785
?
为什么输出不是[9e]abf5b536662000f79978c4d1b6e4eff5c8d785
?我知道前两个字符 ( 9e
) 是十六进制的长度。我应该如何散列 的内容fi
以便获得 git ref abf5b536662000f79978c4d1b6e4eff5c8d785
?
采纳答案by VonC
As described in "How is git commit sha1 formed ", the formula is:
如“ git commit sha1 是如何形成的”中所述,公式为:
(printf "<type> %s(printf "commit %s(printf "commit %s(printf "tag %sgit cat-file -t <hash>
" $(git cat-file tag v2.4.2 | wc -c); git cat-file tag v2.4.2)|sha1sum
" $(git cat-file commit v2.4.2{} | wc -c); git cat-file commit v2.4.2{})|sha1sum
" $(git cat-file commit 9eabf5b536662000f79978c4d1b6e4eff5c8d785 | wc -c); git cat-file commit 9eabf5b536662000f79978c4d1b6e4eff5c8d785 )|sha1sum
" $(git cat-file <type> <ref> | wc -c); git cat-file <type> <ref>)|sha1sum
In the case of the commit9eabf5b536662000f79978c4d1b6e4eff5c8d785 (which is v2.4.2^{}
, and which referenced a tree) :
在提交9eabf5b536662000f79978c4d1b6e4eff5c8d785(它是v2.4.2^{}
,并且引用了树)的情况下:
git cat-file -p 9eabf5b536662000f79978c4d1b6e4eff5c8d785
That will give 9eabf5b536662000f79978c4d1b6e4eff5c8d785.
这将给出 9eabf5b536662000f79978c4d1b6e4eff5c8d785。
As would:
就像:
git hash-object fi
(still 9eabf5b536662000f79978c4d1b6e4eff5c8d785)
(还是 9eabf5b536662000f79978c4d1b6e4eff5c8d785)
Similarly, computing the SHA1 of the tag v2.4.2 would be:
类似地,计算标签 v2.4.2 的 SHA1 将是:
echo "blob 277##代码##$(cat fi)" | shasum
That would give 29932f3915935d773dc8d52c292cadd81c81071d.
这将给出 29932f3915935d773dc8d52c292cadd81c81071d。
回答by Sulli
There's bit of confusion here. Git uses different types of objects: blobs, trees and commits. The following command:
这里有点混乱。Git 使用不同类型的对象:blob、trees 和 commits。以下命令:
##代码##Tells you the type of object for a given hash. So in your example, the hash 9eabf5b536662000f79978c4d1b6e4eff5c8d785 corresponds to a commit object.
告诉您给定散列的对象类型。因此,在您的示例中,哈希 9eabf5b536662000f79978c4d1b6e4eff5c8d785 对应于提交对象。
Now, as you figured out yourself, running this:
现在,正如你自己想的那样,运行这个:
##代码##Gives you the content of the object according to its type (in this instance, a commit).
根据对象的类型(在本例中为提交)为您提供对象的内容。
But, this:
但是这个:
##代码##...computes the hash for a blob whose content is the output of the previous command (in your example), but it could be anything else (like "hello world!"). Here try this:
...计算一个 blob 的哈希值,该 blob 的内容是上一个命令的输出(在您的示例中),但它可以是其他任何内容(例如“hello world!”)。在这里试试这个:
##代码##The output is the same as the previous command. This is basically how Git hashes a blob. So by hashing fi, you are generating a blob object. But as we have seen, 9eabf5b536662000f79978c4d1b6e4eff5c8d785 is a commit, not a blob. So, you cannot hash fi as it is in order to get the same hash.
输出与上一个命令相同。这基本上是 Git 散列 blob 的方式。因此,通过对 fi 进行散列,您将生成一个 blob 对象。但正如我们所见,9eabf5b536662000f79978c4d1b6e4eff5c8d785 是一个提交,而不是一个 blob。因此,您不能按原样散列 fi 以获得相同的散列。
A commit's hash is based on several other informations which makes it unique (such as the committer, the author, the date, etc). The following article tells you exactly what a commit hash is made of:
提交的哈希值基于其他一些使其独一无二的信息(例如提交者、作者、日期等)。以下文章准确地告诉您提交哈希是由什么组成的:
So you could get the same hash by providing all the data specified in the article with the exact same values as those used in the original commit.
因此,您可以通过为文章中指定的所有数据提供与原始提交中使用的值完全相同的值来获得相同的哈希值。
This might be helpful as well:
这也可能有帮助: