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

时间:2018-03-25 07:25:10

标签: git git-diff

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

dubbo的合并提交a4632dad6cf5ecdbcd8e4f357c69f3b34afc04f0为例。 a4632dad的代码行是 155784 ,它是通过运行命令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

1 个答案:

答案 0 :(得分:1)

合并提交只是一个常规提交,恰好有多个父级。

在您提及的情况下,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与合并a4632dad6cf5区分开来:

$ 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 $3}' | xargs -n1 git cat-file blob | wc -l
  155131
$ git ls-tree -r a4632dad6cf5 | grep '\.java$' | awk -F' ' '{print $3}' | xargs -n1 git cat-file blob | wc -l
  155784