以机器可读格式获取 git revlist 的输出

Get output of git revlist in machine-readable format

我正在使用 git rev-list --all --format="%H%n%B" 检索 git 存储库的所有(可访问)提交。

我需要能够将结果输出解析为 提交哈希 以及 原始主体 的单独字段。

-> 是否有任何 稳健 的方式来格式化输出以使其能够被解析?

虽然提交哈希的长度是固定的,但原始正文中有数量未知的行,因此需要某种分隔符。我考虑过像标签一样将输出包装在 xml 中,例如--format="<record>%H%n%B</record>",但这有一个明显的缺点,即如果将字符串 </record> 插入到原始正文中,将会阻止解析器。当然,我可以使定界符更复杂,以降低有人将它们插入提交消息的风险,但我真正需要的是一个从技术上讲不能成为原始主体一部分的字符。我尝试使用 ASCII 控制字符作为记录分隔符“\x1F”。但是,它并没有按预期插入到输出中,而是按原样打印出来。


根据 torek 的回复(谢谢!)我能够创建一个小的 python 函数:

from subprocess import Popen, PIPE
from codecs import decode

directory = '/path/to/git/repo'

git_rev_list = Popen(['git', '-C', directory, 'rev-list', '--all'], stdout=PIPE)
git_cat_file = Popen(['git', '-C', directory, 'cat-file', '--batch'],
                     stdin=git_rev_list.stdout, stdout=PIPE)
while True:
    line = git_cat_file.stdout.readline()
    try:
        hash_, type_, bytes_ = map(decode, line.split())
    except ValueError:
        break
    content = decode(git_cat_file.stdout.read(int(bytes_)))
    if type_ == 'commit':
        yield _get_commit(hash_, content)
    git_cat_file.stdout.readline()

您使用“\x1F”走在正确的道路上,但它应该是“%x1F”,您可以开始了。

来自 git rev-list 的联机帮助页:

· %x00: print a byte from a hex code

要通过格式插入 ASCII RS,请使用 %x1F,而不是 \x1F

一般来说,最好的办法是单独进行尸体检索,因为 %B 可以从字面上扩展到任何东西,而且没有可用的保护措施。通常很容易 运行 git log --no-walk --pretty=format:%B 一次提交一个,只是很慢。

要加快速度,您可以使用 git cat-file --batch 或类似的方法,确实 提供了一种在程序中解析数据的简单方法:每个对象前面都有其尺寸。提交对象也很容易解析,因为 %B 等价物只是 "everything after the first two adjacent newlines"。因此,而不是:

git rev-list --all --format=something-tricky | ...

您可以使用:

git rev-list --all | git cat-file --batch | ...

并修改预期的输入格式以预期 <hash> <type> <size-in-bytes> LF <bytes> 的序列。或者,将格式指令添加到 git cat-file 以放弃对象类型(但我会保留它,因为这意味着您可以区分提交和带注释的标签)。