首先,让我引用the gitattributes documentation:
ident
当属性ident 是
设置路径,Git 将 blob 对象中的 $Id$ 替换为
$Id:,后跟 40 个字符的十六进制 blob 对象
结帐时,名称后跟美元符号$。任何
工作树中以$Id: 开头并以$ 结尾的字节序列
签入时文件被替换为$Id$。
所以签出文件中的 ID 是 blob 哈希 ID,而不是 commit 哈希 ID。 Blob 哈希 ID 具体(当前)是数据文件内容的 SHA-1 校验和,前面是文字文本 blob、空格、以字节为单位的数据大小的 ASCII 字段表示和 NUL字节'\0'。
(当然,这是带有$Id$的数据,而不是插入哈希ID的数据。因此,如果源文件由$Id$\nhello\n组成,\n代表换行符,我们要计算SHA -1 的输出:
printf 'blob 11\0$Id$\nhello\n'
因为$Id$\nhello\n 是 11 个字节长。因此,此 blob 的哈希 ID 为 173cbef4e466bed5350cae075633cb81d1e01743。)
这些不保证是可逆的,因为您可以从二进制文件中获得的身份信息可能不足以识别一个特定的提交。举一个经典的例子,考虑一个由单个 main.c 构建的程序:
#ident "$Id$"
但是 Makefile 本身有 -D 选择某些东西的选项,而 main.c 有 #ifdef FEATURE1 等等。
Build #1 是使用带有 -DFEATURE1 的 Makefile 制作的。 Build #2 是使用没有 -D 的 Makefile 制作的。这两个不同的构建来自不同的提交,但它们对于文件 main.c 具有相同的 blob 哈希 ID,因此通过将编译后的 main.o ident 行与 libc 链接生成的两个不同的二进制文件具有相同的哈希。
你能得到的最接近的是:
- 收集所有可以获取的ID;
- 检查每个潜在构建的源树以确定相应输入的 blob 哈希 ID;和
- 列出所有匹配的提交。
如果幸运的话,只有一个匹配的提交。
剩下的问题是如何做上面的事情。大概您将使用您已经使用的任何程序从二进制文件中提取身份信息,作为第一个要点。第二个和第三个,你必须写一个脚本。
脚本本身很短:您只需要查看每个潜在的构建并提取相应的 blob 哈希。因此,找到一个可能是构建的提交,然后在该提交上使用git ls-tree -r $commithash 从git ls-tree -r 获取输出。 (在一次提交时运行一次git ls-tree -r 以查看输出;注意每个mode 100644 或mode 100755 文件的blob 哈希ID。)
现在,将已知目标文件“ident”与相应的源文件 blob 哈希 ID 进行匹配。如何进行此映射取决于您,并且取决于您使用的工具和语言。如果所有已知的 ident 值都匹配所有正确的来源,$commithash 是一个候选哈希,所以打印它。
重复所有候选提交,您将在此处获得最佳答案。
(而且,正如您现在所看到的,ident 过滤器并不是很有用:在构建过程中,最好使用git describe 来获得可用的标识并将其粘贴到构建输出中。)