如何在 Git 中计算两个提交之间更改的行数?

1110

有没有简单的方法在Git中计算两个提交之间更改的行数?

我知道可以使用 git diff 命令,然后数行数,但这似乎很繁琐。 我还想知道如何仅包括我的提交在行数统计中。

17个回答

1539

你需要使用git diff命令的--stat选项,或者如果你想在脚本中解析它,可以使用--numstat选项。

git diff --stat <commit-ish> <commit-ish>

--stat 会产生人类可读的输出,这通常是在合并后所看到的;--numstat 会生成漂亮的表格布局,脚本可以很容易地解释。

我不知道你想一次对多个提交进行此操作,但这是 git log 的任务。Ron DeVera 提到了这一点,但实际上你可以做更多的事情。因为 git log 在打印请求的信息时内部调用了差异发现机制,所以你可以给它任何 diff 统计选项,而不仅仅是 --shortstat。你可能想要使用的是:

git log --author="Your name" --stat <commit1>..<commit2>

但是你也可以使用--numstat--shortstatgit log还可以通过其他各种方式选择提交 - 查看文档。您可能会对像--since(而不是指定提交范围,只选择自上周以来的提交)和--no-merges(合并提交实际上不引入更改),以及漂亮的输出选项(--pretty = oneline,short,medium,full ... )感兴趣。

这里有一个一行代码,可以从git log中获取总更改而不是每个提交的更改(根据需要更改提交选择选项 - 这是您的提交,从commit1到commit2):

git log --numstat --pretty="%H" --author="Your Name" commit1..commit2 | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("+%d, -%d\n", plus, minus)}'

(您需要让git log打印有关提交的某些标识信息;我任意选择了哈希值,然后使用awk仅选择具有三个字段的行,这些行包含状态信息)


7
这并没有回答关于“更改行”的原始问题。一行更改被计算为已插入和已删除的行。计算更改行数需要比这里描述的更多的工作量。 - Ville Laitila
17
@VilleLaitila:如果不付出过多的努力,这已经是最接近实际情况的了,而且对于原帖和其他15个人来说已经足够好了。(如何定义哪些修改行成为添加行和删除行?通过编辑距离计算-和+行之间的差异,作为行长度的一部分比例。) 我们都知道更改会加倍计算; 我们可以将其视为衡量更改量的有用指标,并继续我们的生活。 - Cascabel
307
我想要的是git diff --shortstat <commit1> <commit2> - Kim
14
参考格式:--since--until的日期格式类似于“昨天”,“1个月2周3天1小时1秒前”或“1979-02-26 18:30:00”。 - juanmirocks
5
是的,这就是为什么该行代码写着 <commit-ish> - 它可以与任何代表提交的东西一起使用,包括字面提交、分支、标签和引用等等。请参见 https://dev59.com/1WAg5IYBdhLWcg3wrMl5。 - Cascabel
显示剩余6条评论

374
git diff --shortstat

此命令只会给出修改和新增的行数,仅适用于未暂存的更改。若要与分支进行比较:

git diff --shortstat some-branch

6
好的!但是请注意,这仅适用于未暂存的更改。 - TomCobo
21
如果你已经使用了 git add 来暂存更改,请确保执行 git diff --shortstat --cached - TomNash
2463个文件已更改,39745次插入(+),21383次删除(-)。实际上,我在过去的一个月里已经删除了大约5k到10k。除了移动文件之外,这几乎是我一直在做的事情。有些不对劲。它没有包括已删除的文件或其他什么吗? - jgmjgm
2
@jgmjgm,请尝试在您的命令中使用git merge-base。您的feature_branch可能只是比最初基于的旧版本的master分支更新,因此您需要针对基于其构建的旧基础执行git diff。可以使用以下命令找到它:git merge-base HEAD master,示例命令:git diff --shortstat $(git merge-base HEAD master) HEAD,示例输出:13个文件已更改,955次插入(+),3次删除(-)。很好,这是正确的。然而,这个命令:git diff --shortstat master显示:1643个文件已更改,114890次插入(+),16943次删除(-) - Gabriel Staples
2
shortstats 不显示行数,而是字符数! - JHBonarius
3
根据文档,--shortstat 显示行数而非字符数:https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---shortstat - Zachary Ryan Smith

254

如果您懒得查看详细记录,可以使用git log --stat命令。


19
我发现这很有用,加了一个“-10”来显示之前的十个提交。 - Choylton B. Higginbottom
8
当您完成查看提交历史记录后,请键入 Q 返回终端。 - Stevoisiak

59
git diff --stat commit1 commit2

编辑:您还需要指定提交(如果没有参数,它将比较工作目录与索引)。例如:

git diff --stat HEAD^ HEAD

比较 HEAD 的父节点和 HEAD 本身。


1
没有必要使用diff-index - diff前端可以处理所有内容;我相信--cached/--staged已经涵盖了diff-index的情况。 (而且没有办法像OP所问的那样使用diff-index来比较两个任意提交。) - Cascabel
这对我来说没有任何输出。 - Mike
@Mike:你漏掉了一个尖角符号吗?你最近的提交是一个合并提交吗?如果 Git 告诉你没有差异,那是因为确实没有差异。 - Cascabel
10
或者如果没有提交,运行命令 git diff --stat HEAD - wieczorek1990
1
此外,您可以使用 HEAD~n 来比较比父级更远的版本,其中 n 是您想要回溯的步数。git diff --stat HEAD~5 HEAD 将显示相对于 HEAD 的最近 5 次提交的合并统计信息。 - Nathan Beck

41

上次提交的简要统计:

git diff --shortstat HEAD~1 HEAD
在我的情况下,这提供了以下信息:
 254 files changed, 37 insertions(+), 10773 deletions(-)

插入和删除会影响行。


26

我刚刚为自己解决了这个问题,所以现在分享一下我的解决方法。这是最终结果:

> git summary --since=yesterday
total: 114 file changes, 13800 insertions(+) 638 deletions(-)

底层命令看起来像这样:

git log --numstat --format="" "$@" | awk '{files += 1}{ins += $1}{del += $2} END{print "total: "files" files, "ins" insertions(+) "del" deletions(-)"}'

请注意日志命令中的$@,以传递您的参数,例如--author="Brian"--since=yesterday

将awk转义并放入git别名中很麻烦,因此我将其放入了可执行脚本中(路径为~/bin/git-stat-sum),然后在我的.gitconfig别名中使用该脚本:

[alias]
    summary = !git-stat-sum \"$@\"

它工作得非常好。最后需要注意的一点是,文件更改指的是文件更改的次数而不是更改的唯一文件数量。这正是我要寻找的,但可能不是您所期望的。

这里还有一个或两个例子。

git summary --author=brian
git summary master..dev
# combine them as you like
git summary --author=brian master..dev
git summary --all

实际上,你可以用git summary替换任何git log命令。


2
它应该被接受为答案,因为它是唯一一个实际回答问题的答案:制作一个总和以显示更改的总行数。其他回复显示每行或每个提交的总数,但没有对它们进行总结。您只需通过用“<commit1>..<commit2>”替换“$@”来改进它。 - bN_
2
以下是适用于Git别名的转义命令:summary = "!git log --numstat --format=\"\" \"$@\" | awk '{files += 1}{ins += $1}{del += $2} END{print \"total: \"files\" files, \"ins\" insertions(+) \"del\" deletions(-)\"}' #" - user1626227
2
如果你将脚本命名为 git-summary 并且它在你的路径中,你可以直接使用 git summary 调用它,而不需要设置别名。详情请参见:https://www.atlassian.com/git/articles/extending-git。 - idbrii

20

假设您想比较从abcd123 (第一次提交)到wxyz789 (最后一次提交)之间的所有提交:

git log wxyz789^..abcd123 --oneline --shortstat --author="Mike Surname"

这会给出简洁的输出,例如:

abcd123 Made things better
 3 files changed, 14 insertions(+), 159 deletions(-)
wxyz789 Made things more betterer
 26 files changed, 53 insertions(+), 58 deletions(-)

1
这个对我来说没有任何输出(我已经提交并验证了--author是正确的,通过在git log中使用它而不使用其他参数)。 - Mike
1
更新了提交顺序并澄清了两个SHAs代表的含义。感谢您的指出 :) - Ron DeVera
3
--shortstat选项非常好用,虽然它只适用于git diff命令(而不是git log)。 - lucke84
有没有一种方法可以获取所有提交的总数? - Douglas Gaskell
命令中的第一个提交必须是最旧的提交,而第二个提交必须是最新的提交,才能显示正确的输出。 我也刚刚使用了 git log HEAD~10..HEAD --oneline --shortstat --author="Mike Surname" 并得到了正确的输出,这似乎更简单易用,在这种情况下,它将扫描最近的 10 个提交,并输出指定作者的提交摘要。 - GreatDane
显示剩余2条评论

19

获取指定时间段内所有变更日志的另一种方法

git log --author="Tri Nguyen" --oneline --shortstat --before="2017-03-20" --after="2017-03-10"

输出:

2637cc736 Revert changed code
 1 file changed, 5 insertions(+), 5 deletions(-)
ba8d29402 Fix review
 2 files changed, 4 insertions(+), 11 deletions(-)

有了较长的输出内容,您可以将其导出到文件以获得更可读的内容。

git log --author="Tri Nguyen" --oneline --shortstat --before="2017-03-20" --after="2017-03-10" > /mnt/MyChangeLog.txt

17

总结这一年的好方法

git diff --shortstat <first commit number of the year> HEAD

获取结果 270 个文件已更改,插入了 19175 行(+), 删除了 1979 行(-)


11
git log --numstat 

只提供数字


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接