我正在尝试创建一个脚本,用于收集每次提交的git存储库的总行数.
你可以跑
git ls-files | xargs wc -l
Run Code Online (Sandbox Code Playgroud)
在git存储库中,它返回总行数.在我的例子中,它返回前三个提交的以下摘要:
0 total
8356 total
170931 total
Run Code Online (Sandbox Code Playgroud)
但是,签出并为每次提交运行此命令都太慢,所以我决定使用
git log --shortstat --reverse --pretty=oneline
Run Code Online (Sandbox Code Playgroud)
它返回insertions并deletions在每次提交中完成.问题是这些数字与上一个命令不匹配.相反,我得到以下差异(之后=>的所有内容都是我的计算,也是" x files changed"前缀不包括在内):
[Nothing as this is the first commit] => 0 total
8357 insertions(+) => 8357 total
142972 insertions(+) => 151329 total
Run Code Online (Sandbox Code Playgroud)
所以,我想知道的是,如果没有第一个命令,我可以快速获得准确的行数.有问题的存储库已有近10年的历史,所以我不确定这是否与差异有关.
更新: Git忽略添加到文件末尾的空行,但它本身并不能解释这一点,因为差异远大于文件计数.
差异也可以用二进制文件来解释.diffstat不计算二进制文件中的"行",而wc -l将计算.wc -l这些二进制文件的输出结果可能不是很准确.
然后必须小心xargs wc -l调用,因为它不能正确地解释打印文件名中的特殊字符(例如空格).要避免该问题,请使用以下-z标志git ls-files将文件名用0字节而不是换行符分隔,然后使用-0参数xargs使其期望文件名为0字节分隔:
$ git ls-files -z | xargs -0 wc -l
Run Code Online (Sandbox Code Playgroud)
然后,无法保证xargs所有文件名都适合一次调用wc,这意味着它可能需要wc -l多次调用.这将导致多个摘要在与其他输出混合时可能很容易被遗漏.对"总"行进行润滑应该会使这更明显:
$ git ls-files -z | xargs -0 wc -l | grep total
Run Code Online (Sandbox Code Playgroud)
如果我正确理解你总是希望每次提交时整个存储库的行总数,而不仅仅是每个提交中更改行的计数,那么有一种更简单的方法可以从git中获取该数据:
$ git diff-tree --shortstat 4b825dc642cb6eb9a060e54bf8d69288fbee4904..
Run Code Online (Sandbox Code Playgroud)
这用于diff-tree比较半魔术"空树"(即第一次提交之前的状态)与当前头部.因此,它总结了所有提交的所有统计信息,并消除了手动汇总数字的需要.
作为参考,使用git将空字符串作为树对象进行散列时,可以获得"空树"散列:
$ echo -n | git hash-object -t tree --stdin
4b825dc642cb6eb9a060e54bf8d69288fbee4904
Run Code Online (Sandbox Code Playgroud)