Git责备:统计数据

Eri*_*ner 191 git

我如何"滥用"指责(或者一些更适合的函数,和/或与shell命令结合使用)来统计存在来自每个提交者的存储库中当前有多少行(代码)?

示例输出:

Committer 1: 8046 Lines
Committer 2: 4378 Lines
Run Code Online (Sandbox Code Playgroud)

Ale*_*lex 162

更新

git ls-tree -r -z --name-only HEAD -- */*.c | xargs -0 -n1 git blame \
--line-porcelain HEAD |grep  "^author "|sort|uniq -c|sort -nr
Run Code Online (Sandbox Code Playgroud)

我在途中更新了一些东西.

对于懒惰你也可以把它放入它自己的命令:

#!/bin/bash

# save as i.e.: git-authors and set the executable flag
git ls-tree -r -z --name-only HEAD -- $1 | xargs -0 -n1 git blame \
 --line-porcelain HEAD |grep  "^author "|sort|uniq -c|sort -nr
Run Code Online (Sandbox Code Playgroud)

将它存储在路径中的某个位置或修改路径并使用它

  • git authors '*/*.c' # look for all files recursively ending in .c
  • git authors '*/*.[ch]' # look for all files recursively ending in .c or .h
  • git authors 'Makefile' # just count lines of authors in the Makefile

原始答案

虽然接受的答案完成了这项工作,但速度很慢.

$ git ls-tree --name-only -z -r HEAD|egrep -z -Z -E '\.(cc|h|cpp|hpp|c|txt)$' \
  |xargs -0 -n1 git blame --line-porcelain|grep "^author "|sort|uniq -c|sort -nr
Run Code Online (Sandbox Code Playgroud)

几乎是瞬间的.

要获取当前跟踪的文件列表,您可以使用

git ls-tree --name-only -r HEAD
Run Code Online (Sandbox Code Playgroud)

此解决方案避免调用file确定文件类型,并出于性能原因使用grep匹配所需的扩展名.如果应包含所有文件,只需将其从行中删除即可.

grep -E '\.(cc|h|cpp|hpp|c)$' # for C/C++ files
grep -E '\.py$'               # for Python files
Run Code Online (Sandbox Code Playgroud)

如果文件可以包含空格,这对于shell可能会使用:

git ls-tree -z --name-only -r HEAD | egrep -Z -z '\.py'|xargs -0 ... # passes newlines as '\0'
Run Code Online (Sandbox Code Playgroud)

给出一个文件列表(通过管道),可以使用xargs来调用命令并分发参数.允许处理多个文件的命令会忽略-n1.在这种情况下,我们调用git blame --line-porcelain并且每次调用我们都使用1个参数.

xargs -n1 git blame --line-porcelain
Run Code Online (Sandbox Code Playgroud)

然后,我们过滤输出"作者"的出现,对列表进行排序,并通过以下方式计算重复行:

grep "^author "|sort|uniq -c|sort -nr
Run Code Online (Sandbox Code Playgroud)

注意

其他答案实际上过滤掉仅包含空格的行.

grep -Pzo "author [^\n]*\n([^\n]*\n){10}[\w]*[^\w]"|grep "author "
Run Code Online (Sandbox Code Playgroud)

上面的命令将打印包含至少一个非空白字符的行的作者.您还可以使用匹配\w*[^\w#],这也将排除第一个非空白字符不是a的行#(在许多脚本语言中注释).

  • OSX用户,尝试以下方法(仍然无法处理名称中带有换行符的文件):`git ls-tree --name-only -r HEAD | grep -E'\.(cc | h | m | hpp | c)$'| xargs -n1 git blame --line-porcelain | grep"^ author"| sort | uniq -c | sort -nr` (4认同)
  • 如果您只想要当前路径下的所有内容,请使用"./"作为路径过滤器(回答者放置"*/*.c"). (3认同)
  • @nilbus:你做不到.`echo"a \nb \nc"| xargs -n1 cmd`将扩展为`cmd a; cmd b; cmd d` (2认同)
  • --line-porcelain似乎不再起作用(git 1.7.5.4)而是使用--porcelain (2认同)
  • 当代码只是重新格式化时,可能会使用"blame -w"来获得更好的代码所有权http://stackoverflow.com/questions/4112410/git-change-styling-whitespace-without-changing-ownership-blame (2认同)
  • 真的很懒:`git config --global alias.authors'!f(){git ls-tree -r -z --name-only HEAD - $ 1 | xargs -0 -n1 git blame --line-porcelain HEAD | grep"^ author"| sort | uniq -c | sort -nr; }; f'` (2认同)
  • 致命:HEAD中没有这样的路径“ HEAD” (2认同)

Lin*_*der 118

我写了一个名为git-fame的宝石,它可能很有用.

安装和使用:

  1. $ gem install git_fame
  2. $ cd /path/to/gitdir
  3. $ git fame

输出:

Statistics based on master
Active files: 21
Active lines: 967
Total commits: 109

Note: Files matching MIME type image, binary has been ignored

+----------------+-----+---------+-------+---------------------+
| name           | loc | commits | files | distribution (%)    |
+----------------+-----+---------+-------+---------------------+
| Linus Oleander | 914 | 106     | 21    | 94.5 / 97.2 / 100.0 |
| f1yegor        | 47  | 2       | 7     |  4.9 /  1.8 / 33.3  |
| David Selassie | 6   | 1       | 2     |  0.6 /  0.9 /  9.5  |
+----------------+-----+---------+-------+---------------------+
Run Code Online (Sandbox Code Playgroud)

  • 它不应该在Windows上工作.*仅限nix. (11认同)
  • 别傻了,@ tcaswell.指向有用的东西并不是垃圾邮件,即使你碰巧是那个写东西的人. (9认同)
  • +1终于1工作,看起来它给出了合理的数字,其余的命令行要么不能在OSX上工作,因为utils不兼容或者在我的repo上给出了很少的数字.这是在OSX和ruby 1.9.3(brew) (4认同)
  • 回答我自己的问题:git fame --exclude = paths/to/files,paths/to/other/files (4认同)
  • 另外,我不知道您在这个问题的上下文中所说的“无关语言”是什么意思。我知道你试图让这个答案看起来很糟糕,但你太努力了。 (2认同)
  • @Adam:你还有问题吗?在OS X 10.9.5上对我很有效. (2认同)
  • 对于任何大于几个的回购承诺,这个宝石需要做的时间是天文数字 (2认同)
  • 当在Windows上使用新的"Ubuntu"功能时,这适用于Windows. (2认同)

Edw*_*son 48

git ls-tree -r HEAD|sed -re 's/^.{53}//'|while read filename; do file "$filename"; done|grep -E ': .*text'|sed -r -e 's/: .*//'|while read filename; do git blame -w "$filename"; done|sed -r -e 's/.*\((.*)[0-9]{4}-[0-9]{2}-[0-9]{2} .*/\1/' -e 's/ +$//'|sort|uniq -c
Run Code Online (Sandbox Code Playgroud)

分步说明:

列出版本控制下的所有文件

git ls-tree -r HEAD|sed -re 's/^.{53}//'
Run Code Online (Sandbox Code Playgroud)

将列表仅剪切为文本文件

|while read filename; do file "$filename"; done|grep -E ': .*text'|sed -r -e 's/: .*//'
Run Code Online (Sandbox Code Playgroud)

Git责怪所有文本文件,忽略空格更改

|while read filename; do git blame -w "$filename"; done
Run Code Online (Sandbox Code Playgroud)

拉出作者姓名

|sed -r -e 's/.*\((.*)[0-9]{4}-[0-9]{2}-[0-9]{2} .*/\1/' -e 's/ +$//'
Run Code Online (Sandbox Code Playgroud)

对作者列表进行排序,并使uniq计算连续重复行的数量

|sort|uniq -c
Run Code Online (Sandbox Code Playgroud)

示例输出:

   1334 Maneater
   1924 Another guy
  37195 Brian Ruby
   1482 Anna Lambda
Run Code Online (Sandbox Code Playgroud)

  • 没关系,'sudo brew install gnu-sed`解决了它.奇迹般有效! (6认同)
  • 或者为MacPorts用户安装`port install gsed`. (5认同)

adi*_*ius 31

git summarygit-extras包提供的正是您所需要的.在git-extras上查看文档- git-summary:

git summary --line
Run Code Online (Sandbox Code Playgroud)

给出如下所示的输出:

project  : TestProject
lines    : 13397
authors  :
8927 John Doe            66.6%
4447 Jane Smith          33.2%
  23 Not Committed Yet   0.2%
Run Code Online (Sandbox Code Playgroud)

  • 很好,但似乎不支持路径过滤器,或者至少不支持子目录参数。会更好。 (2认同)

gtd*_*gtd 6

Erik的解决方案非常棒,但我在变音符号方面遇到了一些问题(尽管我的LC_*环境变量表面上设置正确),并且噪声通过实际上有日期的代码行泄漏.我的sed-fu很差,所以我最终得到了这个带有红宝石的frankenstein片段,但它在200,000+ LOC上完美无缺地工作,并对结果进行排序:

git ls-tree -r HEAD | gsed -re 's/^.{53}//' | \
while read filename; do file "$filename"; done | \
grep -E ': .*text' | gsed -r -e 's/: .*//' | \
while read filename; do git blame "$filename"; done | \
ruby -ne 'puts $1.strip if $_ =~ /^\w{8} \((.*?)\s*\d{4}-\d{2}-\d{2}/' | \
sort | uniq -c | sort -rg
Run Code Online (Sandbox Code Playgroud)

另请注意,gsed而不是sed因为这是二进制自制软件安装,使系统保持原样.


Tho*_*ner 5

这是@Alex 回答中的主要片段,它实际上执行了聚合责备线的操作。我已将其缩减为对单个文件而不是一组文件进行操作。

git blame --line-porcelain path/to/file.txt | grep  "^author " | sort | uniq -c | sort -nr
Run Code Online (Sandbox Code Playgroud)

我在这里发布这个是因为我经常回到这个答案并重新阅读帖子并重新消化示例以提取我认为它征税的部分。对于我的用例来说,它也不够通用;它的范围是整个 C 项目。


我喜欢列出每个文件的统计信息,通过使用 bashfor迭代器而不是xargs因为我发现 xargs 可读性较差且难以使用/记忆而实现,应该在别处讨论xargs 与 for的优点/缺点。

这是一个实用的片段,将分别显示每个文件的结果:

for file in $(git ls-files); do \
    echo $file; \
    git blame --line-porcelain $file \
        | grep  "^author " | sort | uniq -c | sort -nr; \
    echo; \
done
Run Code Online (Sandbox Code Playgroud)

我测试过,在 bash shell 中直接运行是 ctrl+c 安全的,如果您需要将其放入 bash 脚本中如果您希望用户能够中断您的 for 循环,您可能需要在 SIGINT 和 SIGTERM 上设置陷阱