主题行中问题的正确答案:
Git 对象 SHA-1 是文件内容还是文件名?
可能“都不是”,因为您指的是松散对象文件的内容,而不是原始文件——即使您指的是原始文件,这仍然不太正确。
在 Git 中,一个松散的对象是一个普通文件。文件名由对象的哈希 ID 构成。反过来,对象的哈希 ID 是通过计算对象内容的哈希以及附加的前缀标头来构造的。
带前缀的标头取决于对象类型。有四种类型:blob
、commit
、tag
和tree
。标头由一个以 0 结尾的字节字符串组成,该字符串由作为 ASCII(或等效的 UTF-8)字节字符串的类型名称组成,后跟一个空格,然后是对象大小的十进制表示(以字节为单位),然后是通过 ASCII NUL(b'\x00'
在 Python 中,如果您更喜欢现代 Python 表示法,或者'\0'
如果您更喜欢 C)。
在标题之后是实际的对象内容。因此,对于包含字节字符串的文件b'hello\n'
,要散列的数据包括b'blob 6\0hello\n
:
$ echo 'hello' | git hash-object -t blob --stdin
ce013625030ba8dba906f756967f9e9ca394464a
$ python3
[...]
>>> import hashlib
>>> s = b'blob 6\0hello\n'
>>> hashlib.sha1(s).hexdigest()
'ce013625030ba8dba906f756967f9e9ca394464a'
因此,用于存储此文件的文件名是(派生自)ce013625030ba8dba906f756967f9e9ca394464a
。作为一个松散的物体,它变成.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
.
然而,该文件的内容b'blob 6\0hello\n'
是 zlib 压缩形式的(显然,level=1
-默认当前为 6,结果在该级别不匹配;尚不清楚 Git 的 zlib deflate 是否与 Python 完全匹配,但使用 level 1确实在这里工作):
$ echo 'hello' | git hash-object -w -t blob --stdin
ce013625030ba8dba906f756967f9e9ca394464a
$ vis .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
x\^AK\M-J\M-IOR0c\M-HH\M-M\M-I\M-I\M-g\^B\000\^]\M-E\^D\^T$
(注意最后$
还是shell提示符;现在回到Python3)
>>> import zlib
>>> zlib.compress(s, 1)
b'x\x01K\xca\xc9OR0c\xc8H\xcd\xc9\xc9\xe7\x02\x00\x1d\xc5\x04\x14'
>>> import vis
>>> print(vis.vis(zlib.compress(s, 1)))
x\^AK\M-J\M-IOR0c\M-HH\M-M\M-I\M-I\M-g\^B\^@\^]\M-E\^D\^T
哪里vis.py
是:
def vischr(byte):
"encode characters the way vis(1) does by default"
if byte in b' \t\n':
return chr(byte)
# control chars: \^X; del: \^?
if byte < 32 or byte == 127:
return r'\^' + chr(byte ^ 64)
# printable characters, 32..126
if byte < 128:
return chr(byte)
# meta characters: prefix with \M^ or \M-
byte -= 128
if byte < 32 or byte == 127:
return r'\M^' + chr(byte ^ 64)
return r'\M-' + chr(byte)
def vis(bytestr):
"same as vis(1)"
return ''.join(vischr(c) for c in bytestr)
(vis
产生二进制文件的可逆但可打印的编码;这是我 1993 年对问题的回答cat -v
)。
请注意,存储在 Git 存储库(在提交下)中的文件名仅显示为存储在单个对象中的路径名组件。tree
计算树对象的哈希 ID 并非易事;我在githash.py下的公共“脚本”存储库中有执行此操作的 Python 代码。