git:自特定提交以来*未*更改的行数?
git: number of lines *not* changed since specific commit?
有很多答案都很好用命令行 fu 来查找更改(或更改统计信息),但我想找到相反的答案:(每个文件)有多少行 not 自特定提交后更改?
我能找到的最接近的是:How to find which files have not changed since commit? 但我想知道有多少行(理想情况下:在每个文件中)保持不变,而不是哪些文件。
所以,基本上:git diff --stat 可以输出 unchanged 除了插入和删除之外的行吗?
或者,我想 git ls-files、git blame 和一些 awk 魔法可能会起作用,但我还没有完全弄明白。 -- 例如,不是用最后一次更改的提交编号标记每一行,我可以使用 git-blame 来指示此更改是在给定提交之前还是之后发生的吗?与 grep 和 wc -l 一起可以让我到达那里。
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
我尝试 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')
想通了。关键是 git blame 可以指定日期范围(参见 https://git-scm.com/docs/git-blame,“指定范围”部分)。假设 123456 是我要比较的提交。有
git blame 123456..
“自范围边界 [...] 以来未更改的行被归咎于该范围边界提交”,也就是说,它将显示自该提交以来未更改的所有内容为“^123456”。因此,每个文件,我的问题的答案是
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-责备更多的选项!
$ 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 -- `wc -l ` `git diff --numstat `
echo $((-)) lines unchanged in since
}
有很多答案都很好用命令行 fu 来查找更改(或更改统计信息),但我想找到相反的答案:(每个文件)有多少行 not 自特定提交后更改?
我能找到的最接近的是:How to find which files have not changed since commit? 但我想知道有多少行(理想情况下:在每个文件中)保持不变,而不是哪些文件。
所以,基本上:git diff --stat 可以输出 unchanged 除了插入和删除之外的行吗?
或者,我想 git ls-files、git blame 和一些 awk 魔法可能会起作用,但我还没有完全弄明白。 -- 例如,不是用最后一次更改的提交编号标记每一行,我可以使用 git-blame 来指示此更改是在给定提交之前还是之后发生的吗?与 grep 和 wc -l 一起可以让我到达那里。
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
我尝试 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')
想通了。关键是 git blame 可以指定日期范围(参见 https://git-scm.com/docs/git-blame,“指定范围”部分)。假设 123456 是我要比较的提交。有
git blame 123456..
“自范围边界 [...] 以来未更改的行被归咎于该范围边界提交”,也就是说,它将显示自该提交以来未更改的所有内容为“^123456”。因此,每个文件,我的问题的答案是
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-责备更多的选项!
$ 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 -- `wc -l ` `git diff --numstat `
echo $((-)) lines unchanged in since
}