假设我有一个文本文件
alex
bob
matrix
will be removed
git repo
我已经将其更新为
alex
new line here
another new line
bob
matrix
git
在这里,我添加了行号(2,3)和更新了行号(6)
如何使用git diff或任何其他git命令获取这些行号信息?
假设我有一个文本文件
alex
bob
matrix
will be removed
git repo
我已经将其更新为
alex
new line here
another new line
bob
matrix
git
在这里,我添加了行号(2,3)和更新了行号(6)
如何使用git diff或任何其他git命令获取这些行号信息?
Answers:
git diff --stat
将显示您在提交内容时获得的输出,我想这就是您所指的内容。
git diff --stat
为了准确显示已更改的行号,您可以使用
git blame -p <file> | grep "Not Committed Yet"
并且更改的行将是结果中括号前的最后一个数字。虽然不是一个干净的解决方案:(
这是一个bash函数,用于从diff计算结果行号:
diff-lines() {
local path=
local line=
while read; do
esc=$'\033'
if [[ $REPLY =~ ---\ (a/)?.* ]]; then
continue
elif [[ $REPLY =~ \+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then
path=${BASH_REMATCH[2]}
elif [[ $REPLY =~ @@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+)(,[0-9]+)?\ @@.* ]]; then
line=${BASH_REMATCH[2]}
elif [[ $REPLY =~ ^($esc\[[0-9;]+m)*([\ +-]) ]]; then
echo "$path:$line:$REPLY"
if [[ ${BASH_REMATCH[2]} != - ]]; then
((line++))
fi
fi
done
}
它可以产生如下输出:
$ git diff | diff-lines
http-fetch.c:1: #include "cache.h"
http-fetch.c:2: #include "walker.h"
http-fetch.c:3:
http-fetch.c:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
http-fetch.c:4:+int main(int argc, const char **argv)
http-fetch.c:5: {
http-fetch.c:6:+ const char *prefix;
http-fetch.c:7: struct walker *walker;
http-fetch.c:8: int commits_on_stdin = 0;
http-fetch.c:9: int commits;
http-fetch.c:19: int get_verbosely = 0;
http-fetch.c:20: int get_recover = 0;
http-fetch.c:21:
http-fetch.c:22:+ prefix = setup_git_directory();
http-fetch.c:23:+
http-fetch.c:24: git_config(git_default_config, NULL);
http-fetch.c:25:
http-fetch.c:26: while (arg < argc && argv[arg][0] == '-') {
fetch.h:1: #include "config.h"
fetch.h:2: #include "http.h"
fetch.h:3:
fetch.h:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix);
fetch.h:4:+int main(int argc, const char **argv);
fetch.h:5:
fetch.h:6: void start_fetch(const char* uri);
fetch.h:7: bool fetch_succeeded(int status_code);
从这样的差异:
$ git diff
diff --git a/builtin-http-fetch.c b/http-fetch.c
similarity index 95%
rename from builtin-http-fetch.c
rename to http-fetch.c
index f3e63d7..e8f44ba 100644
--- a/builtin-http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,9 @@
#include "cache.h"
#include "walker.h"
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
{
+ const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
int get_verbosely = 0;
int get_recover = 0;
+ prefix = setup_git_directory();
+
git_config(git_default_config, NULL);
while (arg < argc && argv[arg][0] == '-') {
diff --git a/fetch.h b/fetch.h
index 5fd3e65..d43e0ca 100644
--- a/fetch.h
+++ b/fetch.h
@@ -1,7 +1,7 @@
#include "config.h"
#include "http.h"
-int cmd_http_fetch(int argc, const char **argv, const char *prefix);
+int main(int argc, const char **argv);
void start_fetch(const char* uri);
bool fetch_succeeded(int status_code);
如果只想显示添加/删除/修改的行,而不是周围的上下文,则可以传递-U0
给git diff:
$ git diff -U0 | diff-lines
http-fetch.c:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
http-fetch.c:4:+int main(int argc, const char **argv)
http-fetch.c:6:+ const char *prefix;
http-fetch.c:22:+ prefix = setup_git_directory();
http-fetch.c:23:+
fetch.h:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix);
fetch.h:4:+int main(int argc, const char **argv);
它对ANSI颜色代码具有鲁棒性,因此您可以传递--color=always
给git diff以获得添加/删除的行的常规颜色编码。
输出可以很容易地grep:
$ git diff -U0 | diff-lines | grep 'main'
http-fetch.c:4:+int main(int argc, const char **argv)
fetch.h:4:+int main(int argc, const char **argv);
在您的情况下git diff -U0
会给出:
$ git diff -U0 | diff-lines
test.txt:2:+new line here
test.txt:3:+another new line
test.txt:6:-will be removed
test.txt:6:-git repo
test.txt:6:+git
如果只需要行号,请将更改echo "$path:$line:$REPLY"
为just,echo "$line"
然后将输出通过管道传输uniq
。
git diff --color
不会通过。还是您认为将颜色转义添加到此函数的返回值中会更好吗?
git diff --color | diff-lines
现在可以正常运行了:)
zsh: parse error near `]+m'
什么想法吗?错误来自此行:elif [[ $REPLY =~ ^($esc\[[0-9;]+m)*([\ +-]) ]]; then
我使用的--unified=0
选项git diff
。
例如,git diff --unified=0 commit1 commit2
输出diff:
由于该--unified=0
选项,diff输出显示0条上下文行;换句话说,它精确地显示了变化的线。
现在,您可以识别以'@@'开头的行,并根据模式进行解析:
@@ -startline1,count1 +startline2,count2 @@
回到上面的示例,对于文件WildcardBinding.java,从910行开始,删除了0行。从911行开始,添加了4行。
@@ -910,10,+911,15@@
什么事情,那么我们怎么确切地说增加,删除或修改了多少行
我遇到了同样的问题,所以我写了一个gawk脚本,将git diff的输出更改为在每行之前添加行号。当我需要比较工作树时,有时我会发现它很有用,尽管不限于此。也许对这里的人有用吗?
$ git diff HEAD~1 |showlinenum.awk
diff --git a/doc.txt b/doc.txt
index fae6176..6ca8c26 100644
--- a/doc.txt
+++ b/doc.txt
@@ -1,3 +1,3 @@
1: red
2: blue
:-green
3:+yellow
您可以从这里下载:https :
//github.com/jay/showlinenum
git diffn
也是这样做的,它完全保留了终端颜色,并在左侧显示了旧文件,在右侧显示了新文件的行号。
所有未提交的行的行号(添加/修改):
git blame <file> | grep -n '^0\{8\} ' | cut -f1 -d:
输出示例:
1
2
8
12
13
14
配置一个外部差异工具,它将显示行号。例如,这就是我在git全局配置中所拥有的:
diff.guitool=kdiff3
difftool.kdiff3.path=c:/Program Files (x86)/KDiff3/kdiff3.exe
difftool.kdiff3.cmd="c:/Program Files (x86)/KDiff3/kdiff3.exe" "$LOCAL" "$REMOTE"
请参阅此答案以获取更多详细信息:https : //stackoverflow.com/q/949242/526535
这是我拼凑的bash函数:
echo ${f}:
for n in $(git --no-pager blame --line-porcelain $1 |
awk '/author Not Committed Yet/{if (a && a !~ /author Not Committed Yet/) print a} {a=$0}' |
awk '{print $3}') ; do
if (( prev_line > -1 )) ; then
if (( "$n" > (prev_line + 1) )) ; then
if (( (prev_line - range_start) > 1 )) ; then
echo -n "$range_start-$prev_line,"
else
echo -n "$range_start,$prev_line,"
fi
range_start=$n
fi
else
range_start=$n
fi
prev_line=$n
done
if (( "$range_start" != "$prev_line" )) ; then
echo "$range_start-$prev_line"
else
echo "$range_start"
fi
它最终看起来像这样:
views.py:
403,404,533-538,546-548,550-552,554-559,565-567,580-582
这可能是更改行的相当准确的计数:
git diff --word-diff <commit> |egrep '(?:\[-)|(?:\{\+)' |wc -l
另外,这是差异中行号的解决方案:https : //github.com/jay/showlinenum
这是一些Python copypasta,用于获取已修改/已删除行的行号,以防您遇到此问题。
将其修改为可以同时获得修改和添加的行号的东西应该很容易。
我只在Windows上进行过测试,但是它也应该跨平台。
import re
import subprocess
def main(file1: str, file2: str):
diff = get_git_diff(file1, file2)
print(edited_lines(diff))
def edited_lines(git_diff: str):
ans = []
diff_lines = git_diff.split("\n")
found_first = False
# adjust for added lines
adjust = 0
# how many lines since the start
count = 0
for line in diff_lines:
if found_first:
count += 1
if line.startswith('-'):
# minus one because count is 1 when we're looking at the start line
ans.append(start + count - adjust - 1)
continue
if line.startswith('+'):
adjust += 1
continue
# get the start line
match = re.fullmatch(r'@@ \-(\d+),\d+ \+\d+,\d+ @@', line)
if match:
start = int(match.group(1))
count = 0
adjust = 0
found_first = True
return ans
def get_git_diff(file1: str, file2: str):
try:
diff_process: subprocess.CompletedProcess = subprocess.run(['git', 'diff', '--no-index', '-u', file1, file2], shell=True, check=True, stdout=subprocess.PIPE)
ans = diff_process.stdout
# git may exit with 1 even though it worked
except subprocess.CalledProcessError as e:
if e.stdout and e.stderr is None:
ans = e.stdout
else:
raise
# remove carriage at the end of lines from Windows
ans = ans.decode()
ans.replace('\r', '')
return ans
if __name__ == "__main__":
main("file1.txt", "file2.txt")