git:自特定提交后行数*未*更改?

时间:2016-05-13 13:58:26

标签: git git-diff git-blame

有很多答案可以通过强大的命令行来查找更改(或更改统计信息),但我想找到相反的结果:有多少行(每个文件)自特定提交以来发生了什么变化?

我能找到的最接近的是:How to find which files have not changed since commit?但我想知道有多少行(理想情况下:在每个文件中)没有变化,而不是哪些文件。

所以,基本上:除了插入和删除之外,还可以git diff --stat输出不变的行吗?

或者,我想象git ls-files,git blame和一些awk魔法可能会做到这一点,但我还没有能够解决它。 - 例如,不是用最后一次更改的提交编号标记每一行,我是否可以获得git-blame来指示在给定提交之前或之后是否发生了此更改?与grep和wc -l一起让我在那里。

4 个答案:

答案 0 :(得分:1)

想出来。关键是git blame可以指定日期范围(参见https://git-scm.com/docs/git-blame,section" SPECIFYING RANGES")。假设123456是我想要比较的提交。随着

git blame 123456..

"自范围边界[...]以来没有改变的行被指责为该范围边界提交",也就是说,它将显示自提交以来未发生变化的所有内容" ^ 123456&#34 ;.因此,每个文件,我的问题的答案是

git blame 123456.. $file | grep -P "^\^123456" | wc -l # unchanged since
git blame 123456.. $file | grep -Pv "^\^123456" | wc -l # new since

包含在bash脚本中以遍历repo(git ls-files)中的所有文件并打印漂亮:

#!/bin/bash

total_lines=0;
total_lines_unchanged=0;
total_lines_new=0;

echo "--- total unchanged new filename ---"

for file in `git ls-files | \
  <can do some filtering of files here with grep>`
do
  # calculate stats for this file
  lines=`cat $file | wc -l`
  lines_unchanged=`git blame 123456.. $file | grep -P "^\^123456" | wc -l`
  lines_new=`git blame 123456.. $file | grep -Pv "^\^123456" | wc -l`

  # print pretty
  lines_pretty="$(printf "%6d" $lines)"
  lines_unchanged_pretty="$(printf "%6d" $lines_unchanged)"
  lines_new_pretty="$(printf "%6d" $lines_new)"
  echo "$lines_pretty $lines_unchanged_pretty $lines_new_pretty $file"

  # add to total
  total_lines=$(($total_lines + $lines))
  total_lines_unchanged=$(($total_lines_unchanged + $lines_unchanged))
  total_lines_new=$(($total_lines_new + $lines_new))
done

# print total
echo "--- total unchanged new ---"

lines_pretty="$(printf "%6d" $total_lines)"
lines_unchanged_pretty="$(printf "%6d" $total_lines_unchanged)"
lines_new_pretty="$(printf "%6d" $total_lines_new)"
echo "$lines_pretty $lines_unchanged_pretty $lines_new_pretty TOTAL"

感谢Gregg的回答,让我更多地了解git-blame的选项!

答案 1 :(得分:0)

git diff HEAD~ HEAD && echo files that changed
git rev-parse HEAD && echo hash of current rev
wc -l <filename> && echo total lines
git blame <filename> | grep -v -c -e"<first8bytesofhash>"  && echo unchanged lines
git blame <filename> | grep -c -e"<first8bytesofhash>" && echo changed lines

答案 2 :(得分:0)

我尝试使用Python:

import commands
s,o=commands.getstatusoutput('git tag start')
s,o=commands.getstatusoutput('git log --pretty=%H --max-parents=0')
roots=o.split()
result=set()
for root in roots:
  s,o=commands.getstatusoutput('git reset root')
  s,o=commands.getstatusoutput('git ls-files')
  all=set(o.split())
  s,o=commands.getstatusoutput('git ls-files --modified')
  modified=set(o.split())
  unchanged=all-modified
  result=result|unchanged
print result
s,o=commands.getstatusoutput('git reset start --hard')

答案 3 :(得分:0)

$ wc -l main.c
718 main.c
$ git diff --numstat v2.0.0 main.c
152     70      main.c

自v2.0.0以来,当前main.c的152行被更改或添加,因此566行从此保持不变。

lines-unchanged-in-since () {
        set -- $2 `wc -l $1` `git diff --numstat $2 $1` 
        echo $(($2-$4)) lines unchanged in $3 since $1
}