开始之前为了方便说明,先安装有个小工具,它是 git 的反写,叫 tig,是一个字符界面的 git 日志工具。可以使用包管理器安装,也可以使用源代码编译安装,地址是 https://github.com/jonas/tig/blob/master/INSTALL.adoc。
安装完成后,在 git 仓库下输入 tig 命令,会显示提交的历史记录,通过方向键或者 vim 的 hjkl 键可以查看每个历史的信息,回车后显示提交的详细信息,q 键退出回到上一层。

首先是提交的指纹 d5d999f34327261749b891acbf06ac9339f90251,这个指纹码是一个 40 位 16 进制数,它是通过 SHA-1 算法得到,全称是 Secure Hash Algorithm 1,意思是安全散列算法1,这种算法是一个单向的函数,根据输出结果不能得到输入内容,但是只要输入内容有一丝一毫的变化,输出结果会不同(后来被证明可能发生碰撞,不过用来做指纹区分没有什么问题)。
在前面章节 git log 加上美化参数,把指纹的显示长度做了缩短,只取了前面的 7 位,因为前面 7 位就可以在仓库中作为唯一的指纹了,使用 git 命令的时就也不用全部输入指纹码。

在命令行中输入 git show 5d999f 和 git show d5d999f34327261749b891acbf06ac9339f90251,是相同的显示结果,多输入几位指纹码也可以,在目前的仓库状态下,输入 git show d5d9 都可以显示,不带指纹码只输入 git show 会显示最后一次提交的信息。
前面提到过 HEAD 就是版本库最后一次的提交,可以通过下面的命令看看 HEAD 的文件构成:
wangbo@wangbo-VirtualBox:~/test/git-demo$ git cat-file commit HEAD
tree 3ecf800bdea3b30b1c7eaf76ef17c9a3d9f09c27
parent bba42353ad195470c311dd27a26248ae0ab5c006
author wangbo <wangbo@develop-developer.com> 1608521565 +0800
committer wangbo <wangbo@develop-developer.com> 1608521565 +0800
ignore tmp
这个 HEAD 的信息包含了文件树 tree 指纹、上一次的指纹 parent、以及提交作者信息,再加上 commit 的文本信息的字符数:
wangbo@wangbo-VirtualBox:~/test/git-demo$ printf "commit %s\0" $(git cat-file commit HEAD | wc -c)
commit 233
合并通过 SHA-1 算法就得到了提交的指纹码,用如下命令验证一下,发现和 git 的提交历史的指纹码相同:
(printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) | shasum

其中用到的 tree 指纹就是文件的内容,用 git cat-file -p 查看一下:
wangbo@wangbo-VirtualBox:~/test/git-demo$ git cat-file -p 3ecf800bdea3b30b1c7eaf76ef17c9a3d9f09c27
100644 blob 5c9a1f4e0f09d3e74ad8ac4c957364f52763bc81 .gitignore
100644 blob ce013625030ba8dba906f756967f9e9ca394464a hello.txt
100644 blob be147a1ee013b8a6288fdd64ad748db29ed4ce41 readme.md
原来指纹码就是 git 把文件树的内容、作者信息、提交的信息、上一次提交的指纹码等综合在一起来算出来的,只要有其中一项不同,它的指纹码就不可能相同了。
关于指纹码的知识就到这里,大致了解怎么计算的即可,当需要使用指纹码的时候,通常使用前面 7 位就 OK 了。