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