我遇到了同样的问题,不过我想出了一个别名解决了这个问题(我使用的是 git 2.8.3)
[alias]
difftoolr = "!git difftool \"$@\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
如何使用:
difftoolr commit1..commit2 -M
(更多示例请见底部)
工作原理:
假设您有三个重命名的文件。其中一个文件内容实际上已更改(因此您想使用差异工具检查它),但其他两个除路径或名称外都相同(您想忽略它们)。
(different) path/file.old -> newPath/file.new
(identical) path/fileB.old -> newPath/fileB.new
(identical) path/fileC.old -> newPath/fileC.new
Alias命令所做的是生成路径规范,明确地排除fileB
和fileC
,即尽管文件名更改了但内容未改变的那些文件。
换句话说,我们正在生成这些文件规范:
-- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new
注意(也许是最棘手的部分):必须同时显式地排除旧文件路径和新文件路径。
为此,我们使用以下指令发出git diff:
-M100%:跟随重命名。这意味着git假设进行了一些重命名,并将考虑此信息来进行成对比较。阈值为100%,这指示git将被视为已重命名那些具有完全相同内容但未更改的文件。
--diff-filter = R:仅列出git认为已重命名的文件,省略其他文件。
--names-only:仅输出文件名,没有其他信息
-R:反向。在脚本的一个部分中,我们交换了比较顺序(类似于交换左侧和右侧),因此它也将输出旧文件名。例如,-R指令将文件newPath/fileB.new列为path/fileB.old。
... sed ... :最后,我们在所有文件名的开头添加了排除指令:(exclude)。
为了处理其他情况,我创建了三个不同的别名(并不是非常优雅,我想要更灵活的东西),因此可以用于指定不同类型的比较。
git difftoolr0 -M
git difftoolr1 HEAD~1..HEAD -M
git difftoolr2 HEAD --cached -M
无论在哪种情况下,"比较的对象" (commits, --cached或其他) 必须作为第一个参数指定。例如,
git difftoolr2 -M HEAD --cached
不起作用 (因为
-M
排在第一位)。
[alias]
difftoolr0 = "!git difftool \"$@\" -- . $((git diff -M100% --diff-filter=R --name-only & git diff -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
difftoolr1 = "!git difftool \"$@\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
difftoolr2 = "!git difftool \"$@\" -- . $((git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only & git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
最后,BeyondCompare也可能适合你的需求(也适合我的需求)。
它很容易地将并排差异切换为“非结构化”差异。后者会剥离文件夹,只保留名称。如果文件名相同(但路径可能不同),则被视为同一文件的两个版本(例如
path/file.png
和
newPath/file.png
)。在这种情况下,如果内容没有改变,则可以使用上方栏中的一个按钮轻松省略它们。
如果出现“命名”冲突(比较的同一侧有多个文件具有相同的名称,位于不同的路径下),它会选择其中一个进行比较,并忽略其他文件。
git difftool "$@" -- . $((git diff "$1" -M100% --diff-filter=R --name-only & git diff "$1" -M100% --diff-filter=R --name-only -R) | sed 's/\(.*\)/:(exclude)\1/g') #: 1: git difftool "$@" -- . $((git diff "$1" -M100% --diff-filter=R --name-only & git diff "$1" -M100% --diff-filter=R --name-only -R) | sed 's/\(.*\)/:(exclude)\1/g') #: Syntax error: Missing '))'
- Christoph Thiede