无法通过跟踪更改的行数获得正确的代码行以进行修订

Can not get correct line of code for revision by tracking number of line changed

我想获取每个修订版的代码行,但我认为每个修订版 git checkout 和 运行 wc -l 太耗时了。因此,我获取了第一个修订版的代码行,然后获取了每个修订版与其第一个父级之间添加和删除的行数。这样,一个修订的代码行应该是其父修订的代码行加上它们之间添加的行数减去它们之间删除的行数。但是,我发现这个公式不适用于某些合并修订。任何人都可以给我任何提示吗?

dubbo 的合并提交 a4632dad6cf5ecdbcd8e4f357c69f3b34afc04f0 为例。 a4632dad 的代码行是 155784 ,这是通过 运行ning 命令 git ls-files -- "*.java"| xargs cat | wc -l 得到的。它的父项之一是 4f3017c7,其代码行是 175829。然后我通过 git diff --shortstat 4f3017c7 a4632dad -- "*.java" 改变了它们之间的线路。结果是226 files changed, 3174 insertions(+), 23239 deletions(-)。 175829+3174-23239=155764 不等于 155784.

合并提交只是碰巧有多个父项的常规提交。

在您提到的情况下,a4632dad6cf5 是合并提交。它的第一个父级是 5b0ab1143b25,第二个父级是 4f3017c71849:

$ git log -1 --format=fuller a4632dad6cf5
commit a4632dad6cf5ecdbcd8e4f357c69f3b34afc04f0 (HEAD)
Merge: 5b0ab114 4f3017c7
Author:     [...]
AuthorDate: Thu Jan 25 14:01:50 2018 +0800
Commit:     [...]
CommitDate: Thu Jan 25 14:01:50 2018 +0800

    Merge branch '2.5.x'

    [...]

如果这是一个常规提交,它根本就没有第二个父级 4f3017c71849

比较合并前后的状态从合并发生的分支的角度,比较第一个父5b0ab1143b25与合并[=16] =]:

$ git diff --shortstat 5b0ab1143b25..a4632dad6cf5 -- '*.java'
 65 files changed, 976 insertions(+), 323 deletions(-)

将此与以下内容进行比较:

$ git checkout 5b0ab1143b25 2>/dev/null
$ git ls-files -- "*.java" | xargs cat | wc -l
  155131
$ git checkout a4632dad6cf5 2>/dev/null
$ git ls-files -- "*.java" | xargs cat | wc -l
  155784

两者的文件数相差653:

155784 - 155131 = 653

5b0ab1143b25a4632dad6cf5之间的加减之和也是653:

976 - 323 = 653

这是一种无需检出即可计算行数的方法(它可以在裸存储库中工作),但也许检出每个提交会更快。这是在有些天真的假设下,即以 .java 结尾的所有内容都是 blob 对象:

$ git ls-tree -r 5b0ab1143b25 | grep '\.java$' | awk -F' ' '{print }' | xargs -n1 git cat-file blob | wc -l
  155131
$ git ls-tree -r a4632dad6cf5 | grep '\.java$' | awk -F' ' '{print }' | xargs -n1 git cat-file blob | wc -l
  155784