git如何计算文件哈希值?

时间:2011-08-29 01:37:12

标签: git hash sha1 checksum git-hash

存储在树对象中的SHA1哈希值(由git ls-tree返回)与文件内容的SHA1哈希值不匹配(由sha1sum返回)

$ git cat-file blob 4716ca912495c805b94a88ef6dc3fb4aff46bf3c | sha1sum
de20247992af0f949ae8df4fa9a37e4a03d7063e  -

git如何计算文件哈希值?它是否在计算哈希值之前压缩内容?

5 个答案:

答案 0 :(得分:107)

  

Git在对象前加上“blob”,后跟长度(作为   人类可读的整数),后跟一个NUL字符

$ echo -e 'blob 14\0Hello, World!' | shasum 8ab686eafeb1f44702738c8b0f24f2567c36da6d

来源:http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html

答案 1 :(得分:33)

我只是通过@Leif Gruenwoldt扩展答案,并详细说明@Leif Gruenwoldt

提供的reference中的内容

自己动手......

  
      
  • 步骤1.在存储库中创建一个空文本文档(名称无关紧要)
  •   
  • 步骤2.暂存和提交文档
  •   
  • 步骤3.通过执行git ls-tree HEAD
  • 识别blob的哈希值   
  • 步骤4.找到blob的哈希为e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
  •   
  • 第5步。抓住你的惊喜并阅读下面的内容
  •   

GIT如何计算其提交哈希值

    Commit Hash (SHA1) = SHA1("blob " + <size_of_file> + "\0" + <contents_of_file>)

文本blob⎵是常量前缀,\0也是常量,是NULL字符。 <size_of_file><contents_of_file>会因文件而异。

请参阅:What is the file format of a git commit object?

那就是所有人!

但是等等!,您是否注意到<filename>不是用于哈希计算的参数?如果两个文件的内容与创建它们的日期和时间及其名称无关,则它们可能具有相同的哈希值。这是Git处理移动和重命名的原因之一,比其他版本控制系统更好。

自己动手(分机)

  
      
  • 步骤6.在同一目录中创建另一个filename的空文件
  •   
  • 步骤7.比较两个文件的哈希值。
  •   

注意:

该链接未提及如何对tree对象进行哈希处理。我不确定算法和参数但是根据我的观察,它可能根据它包含的所有blobstrees(可能是它们的哈希)来计算哈希值

答案 2 :(得分:13)

<强> git hash-object

这是验证测试方法的快捷方法:

s='abc'
printf "$s" | git hash-object --stdin
printf "blob $(printf "$s" | wc -c)\0$s" | sha1sum

输出:

f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f
f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f  -

其中sha1sum在GNU Coreutils中。

然后归结为理解每种对象类型的格式。我们已经涵盖了琐碎的blob,以下是其他内容:

答案 3 :(得分:3)

基于Leif Gruenwoldt回答,这是shell函数替代git hash-object

git-hash-object () { # substitute when the `git` command is not available
    local type=blob
    [ "$1" = "-t" ] && shift && type=$1 && shift
    # depending on eol/autocrlf settings, you may want to substitute CRLFs by LFs
    # by using `perl -pe 's/\r$//g'` instead of `cat` in the next 2 commands
    local size=$(cat $1 | wc -c | sed 's/ .*$//')
    ( echo -en "$type $size\0"; cat "$1" ) | sha1sum | sed 's/ .*$//'
}

测试:

$ echo 'Hello, World!' > test.txt
$ git hash-object test.txt
8ab686eafeb1f44702738c8b0f24f2567c36da6d
$ git-hash-object test.txt
8ab686eafeb1f44702738c8b0f24f2567c36da6d

答案 4 :(得分:3)

我需要这个用于Python 3中的一些单元测试,所以我想把它留在这里。

def git_blob_hash(data):
    if isinstance(data, str):
        data = data.encode()
    data = b'blob ' + str(len(data)).encode() + b'\0' + data
    h = hashlib.sha1()
    h.update(data)
    return h.hexdigest()

我坚持\n行结尾,但在某些情况下,Git也可能是changing your line endings,然后再计算此哈希值,因此您可能还需要.replace('\r\n', '\n')