似乎能够过滤差异非常方便,因此不会显示琐碎的变化。我想写一个正则表达式,它将在该行上运行,然后传递另一个字符串,使用捕获的参数生成规范形式。如果之前和之后的行产生相同的输出,那么它们将从差异中移除。
例如,我正在开发一个PHP代码库,其中大量的数组访问被写为my_array[my_key]
,如果my_array["my_key"]
my_key
那么{{1}}常量是{{1}}定义。生成差异是很有用的,其中线上唯一的变化是没有添加一些引号。
我无法一次更改所有内容,因为我们没有足够的资源来测试整个代码库,因此每当我对函数进行更改时都要修复它。我怎样才能做到这一点?还有其他类似的东西,我可以用来实现类似的结果。例如,一个更简单的方法可能是跳过规范形式,只看输入是否转换为输出。顺便说一句,我正在使用Git
答案 0 :(得分:7)
$ git diff --help
-G<regex>
Look for differences whose added or removed line matches the given <regex>.
修改强>:
经过一些测试,我有类似
的东西git diff -b -w --word-diff-regex='.*\[[^"]*\]'
然后我输出如下:
diff --git a/test.php b/test.php
index 62a2de0..b76891f 100644
--- a/test.php
+++ b/test.php
@@ -1,3 +1,5 @@
<?php
{+$my_array[my_key]+} = "test";
?>
diff --git a/test1.php b/test1.php
index 62a2de0..6102fed 100644
--- a/test1.php
+++ b/test1.php
@@ -1,3 +1,5 @@
<?php
some_other_stuff();
?>
也许它会对你有所帮助。我在http://www.rhinocerus.net/forum/lang-lisp/659593-git-word-diff-regex-lisp-source.html找到了它,并且有关此thread
的更多信息<强> EDIT2 强>:
git diff -G'\[[A-Za-z_]*\]' --pickaxe-regex
答案 1 :(得分:6)
Git的diff
命令似乎没有任何选项来支持你想要做的事情。但是,您可以使用GIT_EXTERNAL_DIFF
environment variable和自定义脚本(或使用首选脚本或编程语言创建的任何可执行文件)来操作补丁。
我假设你在Linux上;如果没有,你可以调整这个概念,以适应您的环境。假设你有一个Git仓库,其中HEAD
有一个文件file05
,其中包含:
line 26662: $my_array[my_key]
包含以下内容的文件file06
line 19768: $my_array[my_key]
line 19769: $my_array[my_key]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key]
line 19776: $my_array[my_key]
您将file05
更改为:
line 26662: $my_array["my_key"]
您将file06
更改为:
line 19768: $my_array[my_key]
line 19769: $my_array["my_key"]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key2]
line 19776: $my_array[my_key]
使用以下shell脚本,我们将其称为mydiff.sh
并将其放在PATH
中的某个位置:
#!/bin/bash
echo "$@"
git diff-files --patch --word-diff=porcelain "${5}" | awk '
/^-./ {rec = FNR; prev = substr($0, 2);}
FNR == rec + 1 && /^+./ {
ln = substr($0, 2);
gsub("\\[\"", "[", ln);
gsub("\"\\]", "]", ln);
if (prev == ln) {
print " " ln;
} else {
print "-" prev;
print "+" ln;
}
}
FNR != rec && FNR != rec + 1 {print;}
'
执行命令:
GIT_EXTERNAL_DIFF=mydiff.sh git --no-pager diff
将输出:
file05 /tmp/r2aBca_file05 d86525edcf5ec0157366ea6c41bc6e4965b3be1e 100644 file05 0000000000000000000000000000000000000000 100644
index d86525e..c2180dc 100644
--- a/file05
+++ b/file05
@@ -1 +1 @@
line 26662:
$my_array[my_key]
~
file06 /tmp/2lgz7J_file06 d84a44f9a9aac6fb82e6ffb94db0eec5c575787d 100644 file06 0000000000000000000000000000000000000000 100644
index d84a44f..bc27446 100644
--- a/file06
+++ b/file06
@@ -1,8 +1,8 @@
line 19768: $my_array[my_key]
~
line 19769:
$my_array[my_key]
~
line 19770: $my_array[my_key]
~
line 19771: $my_array[my_key]
~
line 19772: $my_array[my_key]
~
line 19773: $my_array[my_key]
~
line 19775:
-$my_array[my_key]
+$my_array[my_key2]
~
line 19776: $my_array[my_key]
~
此输出未显示file05
和file06
中添加的引号的更改。外部diff脚本基本上使用Git diff-files
命令来创建补丁,并通过GNU awk
脚本过滤输出来操作它。此示例脚本不处理GIT_EXTERNAL_DIFF
中提到的旧文件和新文件的所有不同组合,也不会输出有效的修补程序,但它应该足以让您入门。
您可以使用Perl regular expressions,Python difflib
或任何您认为合适的方式来实现符合您需求的外部差异工具。
答案 2 :(得分:3)
grepdiff可用于过滤diff文件中的帅哥。
$ git diff -U1 | grepdiff 'console' --output-matching=hunk
它只显示与给定字符串匹配的帅哥&#34; console&#34;。
答案 3 :(得分:2)
来自我自己的git --help
- 字的Diff-正则表达式=
<regex>
使用
<regex>
来决定单词是什么,而不是将非空格的运行视为单词。还暗示--word-diff除外 它已经启用了。<regex>
的每个非重叠匹配都被视为一个单词。这些匹配之间的任何内容都被视为空格和 忽略(!)以找到差异。您可能希望将|[^[:space:]]
附加到正则表达式以确保 它匹配所有非空白字符。包含换行符的匹配项会在换行符处以静默方式截断(!)。 也可以通过diff驱动程序或配置选项设置正则表达式,请参阅gitattributes(1)或git-config(1)。明确地给它 覆盖任何差异驱动程序或配置设置。差异驱动程序会覆盖配置设置。
答案 4 :(得分:1)
在第一步中规范化输入文件,然后比较规范化的文件。这使您可以最大程度地控制该过程。例如。您可能只想将正则表达式应用于代码的非HTML部分,而不是在字符串内部,而不是在注释内部(或完全忽略注释)。 计算规范化代码的差异是做这些事情的正确方法;在单行上使用正则表达式更容易出错,最多只是一个黑客攻击。
一些差异工具,例如meld
允许隐藏“无关紧要”的差异,并附带一组默认模式,例如隐藏仅限空白的更改。我想这就是你想要的。
答案 5 :(得分:0)
我使用的方法结合git diff
并在结果上应用正则表达式匹配。在一些测试代码(PERL)中,我知道当测试的结果文件中存储的OutputFingerprint
没有改变时,测试是成功的。
首先,我做了一个
my $matches = `git diff -- mytestfile`
然后评估结果:
if($matches =~ /OutputFingerprint/){
fail();
return 1;
}else{
ok();
return 0;
}
答案 6 :(得分:0)
我提供了一个类似问题的答案here。
我制作了一个 git 函数来执行此操作,并将正则表达式作为唯一输入。只需将其输入您的 gitconfig(我使用我的全局 gitconfig)并将其与 git regexadd <regex>
一起使用。
[alias]
regexadd = "!f() { git diff -U0 \
| grepdiff -E $1 --output-matching=hunk \
| git apply --cached --unidiff-zero; }; f"
答案 7 :(得分:-2)
如果目标是最大限度地减少琐碎的差异,您可以考虑我们的SmartDifferencer工具。
这些工具会比较语言语法,而不是布局,因此会忽略许多微不足道的更改(布局,修改后的注释,甚至更改数字的基数),也不会报告。 每个工具都有一个完整的语言解析器;有许多语言的版本,包括PHP。
它不会将示例$ FOO [abc]处理为与$ FOO [“abc”]“语义相同”,因为它们不是。如果abc actaully定义为常量,则$ FOO [“abc”]在语义上不等同。