您可以使用
--word-diff=porcelain
的模式
git diff
(以及传递给
-U
选项,以保留更改之间的所有上下文),并使用足够简单的脚本处理其输出,以更正错误的替换。
--word-diff[=<mode>]
显示单词diff,使用
<mode>
划界改变的单词。默认情况下,单词由空格分隔;
看见
--word-diff-regex
在下面这个
<模式>
默认为
plain
和
必须是以下内容之一:
-
。。。
-
porcelain
:使用专用于脚本使用的基于行的格式。添加/删除/未更改的运行以通常的方式打印
统一的差异格式,以+/-/``字符开头
线的起点和延伸到线的终点。换行符
在输入中,由颚化符表示
~
在自己的线路上。
下面是一个原型
sed
-基于上述方法的实施。
用法
:
fix_wrong_replacements
path
revision
replacement_fix
哪里
影响
:
假设文件的工作副本位于
路径
比较时
至其承诺修订版
修订
包含替换的结果
某些实例
orig_pattern
具有
incorrect_replacement_str
,则,
确定这些替换并将其更改为
correct_replacement_str
。
示例
:
# In last two commits (and, maybe, in the working copy) some "int"s
# were incorrectly changed to "unsigned", now change those to "long"
$myname main.c HEAD~2 /int/unsigned/long/
# In the working copy of somefile.txt all "abc" case-insensitive words
# were changed to "pqrs", now change them to "xyz"
$myname somefile.txt HEAD '/[aA][bB][cC]/pqrs/xyz/'
已知限制/问题
:
-
它适用于单个文件。要修复提交、提交范围或本地更改中的所有错误替换,必须标识更改文件的列表,并在循环中为所有文件调用此脚本。
-
如果在原始(错误)更换过程中使用了不区分大小写的模式,则
orig\U模式
部分
替换\u修复
参数必须使用
[aA]
,则,
[bB]
等,每个字母的正则表达式原子。
-
不处理与其他更改直接相邻的替换。
-
有时可能会添加多余的空行(因为
git diff --word-diff
)
修复\u错误的\u替换
:
#!/usr/bin/env bash
myname="$(basename "$0")"
if [ $# -ne 3 ]
then
cat<<END
Usage:
$myname <path> <revision> <replacement_fix>
where
- <path> is the (relative) path of the file in the working tree
- <revision> is the revision since which the wrong replacements that
must be fixed were made
- <replacement_fix> is a string of the form
/orig_pattern/incorrect_replacement_str/correct_replacement_str/
Effects:
Assuming that the working copy of the file at <path> when compared
to its committed revision <revision> contains results of replacing
certain instances of <orig_pattern> with <incorrect_replacement_str>,
identifies those replacements and changes them to <correct_replacement_str>.
Examples:
$myname main.c HEAD~2 /int/unsigned/long/
$myname somefile.txt HEAD '/[aA][bB][cC]/pqrs/xyz/'
END
exit 1
fi
file="$1"
revision="$2"
s=(${3//// })
orig_pattern="${s[0]}"
incorrect_replacement="${s[1]}"
correct_replacement="${s[2]}"
pat="-$orig_pattern\n+$incorrect_replacement"
git_word_diff()
{
git diff -U100000 \
--word-diff=porcelain \
--word-diff-regex='[[:alpha:]][[:alnum:]]*' \
"$@"
}
word_diff_file="$(mktemp)"
trap "rm $word_diff_file" EXIT
git_word_diff "$revision" -- "$file" > "$word_diff_file"
sed -n -e '
1,5 d;
/^-/ N;
/\n~$/ d;
/\n[- ]/ D;
/^'"$pat"'$/ {x;G;s/\n'"$pat"'$/'"$correct_replacement"'/;x;d;};
/^-.*\n+/ {s/^-.*\n+//;H;x;s/\n//;x;d;};
/^~$/ {s/.*//;x;p;d;};
{s/^.//;H;x;s/\n//;x;};
' "$word_diff_file" > "$file"