【问题标题】:How to generate Git statistics of changes per filetype?如何生成每个文件类型更改的 Git 统计信息?
【发布时间】:2020-08-24 00:33:56
【问题描述】:

在 git 存储库中每个文件类型添加和删除了多少行代码?最好能够为过去的X 提交请求这些统计信息。所以说我会为过去的100 提交请求这个,我的预期结果是这样的:

.css, 100 files changed,  2879 insertions(+), 1134 deletions(-)
.js,   17 files changed,   415 insertions(+),  502 deletions(-)
.php,   6 files changed,   478 insertions(+),  176 deletions(-)
.py,   10 files changed,   156 insertions(+),   56 deletions(-)

这一定是可能的,但我找不到解决方案。我已阅读 this question 并尝试使用 GitstatsRepoExplorer

【问题讨论】:

  • 非常有趣的问题。
  • 你能确认一下当两次提交(例如,相互抵消)时你期望的输出是什么?那么,提交和随后的还原是否应该显示为 0 次插入和 0 次删除?

标签: git


【解决方案1】:

有两种方法可以计算您想要的数据。其中一个是计算整个提交范围的差异,另一个是单独计算每个提交并对值求和。如果多次触摸文件,后者可能会大于前者。既然你没有具体说明,那我就给你看一下。

要计算更简单的前者,您可以使用如下命令:

git diff --numstat BASE_COMMIT.. | ruby -rset -e '
  x = {}
  while gets
    line = $_.chomp.split("\t")
    chunks = line[2].split(".")
    next if chunks.length == 1
    type = chunks[-1]
    x[type] ||= [0, 0, Set.new]
    2.times { |i| x[type][i] += line[i].to_i }
    x[type][2] << line[2]
  end
  x.sort_by { |(k, v)| k }.each do |(type, (add, del, set))|
    puts ".#{type} #{set.length} files changed, #{add} insertions(+), #{del} deletions(-)"
  end'

这使用git diff --numstat 处理从BASE_COMMIT 到当前分支的提交并运行操作。如果你想处理最后的X 提交,写HEAD~X。请注意,这会忽略没有后缀的文件,并将二进制文件视为没有添加或删除行。它也不会产生对齐的列,但您可以根据需要添加它。您还可以使用不同的语言或脚本来代替单行。

如果您想计算所有单个提交的总和,请将 git diff 调用替换为:

git rev-list BASE_COMMIT.. | xargs -I{} git diff --numstat {}^..{}

【讨论】:

  • 非常好的答案!
  • 这会导致像.scss 60 files changed, 5352 insertions(+), 276 deletions(-) .scss} 3 files changed, 38 insertions(+), 13 deletions(-) 这样的行,注意第二行.scss 之后的}。你明白为什么会发生这种情况吗?
  • 可能是由于重命名支持。尝试将 --no-renames 作为 git diff 调用的一部分。
  • 认为你是对的。这个答案非常好。唯一缺少的是它不考虑包含多个. 的文件,例如example.something.ext
【解决方案2】:

我会把这个问题分成子问题:

原始日志魔法

我会从指定问题相对容易的起点开始

如果你跑了

git log

然后您会看到提交摘要列表。当然,这还不够友好。

现在,让我们限制我们的域,假设我们对最近 100 次提交的统计数据感兴趣:

git log -100

现在有问题的提交数量是合适的。但是我们仍然看不到添加和删除,让我们纠正一下:

git log -100 --stat

开始变得更好了,对吗?让我们进一步改进它:

git log -5 --stat --format=""

好多了。现在,对于每个提交,您都有“有用的行”,即包含更改次数的行和格式为的最后一行

9 个文件更改,189 个插入 (+),1 个删除 (-)

基本上,如果您有一行包含“文件已更改”或“文件已更改”,则需要忽略它,除非您有一个具有该名称的文件。所有其他行都是有用的原始输入。

统计算法

您需要一个包含文件类型作为键和一对数字作为值的数据结构。第一个数字是负数,第二个数字是正数。伪代码:

For Each ln In Lines Do
    If (Not ln.Replace("files", "file").Contains("file changed")) And ln.Contains(".") Then
        FileExtension = ln.Substring(ln.IndexOf(".") + 1, ln.IndexOf(" "))
        If (Not Extensions.Has(FileExtension)) Then
            Extensions(FileExtension) = [0, 0]
        End
        UsefulSubstring = ln.Substring(ln.LastIndexOf(" ") + 1)
        For Each char In UsefulSubstring Do
            If char = '+' Then
                Extensions(FileExtension)[1] = Extensions(FileExtension)[1] + 1
            Else
                Extensions(FileExtension)[0] = Extensions(FileExtension)[0] + 1
            End If
        End For
    End If
End For

此算法将构建您的输出,您需要以您喜欢的格式将其放入控制台输出中。因此,您可以使用您喜欢的输入调用此程序。您甚至可以将 git log 命令嵌入到项目中。这不是一项非常大的任务,所以如果你投入几个小时,也许更少,你就会得到你需要的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2011-08-24
    • 2011-09-30
    • 2014-02-01
    • 1970-01-01
    相关资源
    最近更新 更多