use*_*155 8 git rename move git-diff meld
我正在使用:
git diff HEAD --diff-filter=R -M
Run Code Online (Sandbox Code Playgroud)
使用meld external diff工具显示已重命名/移动和修改的文件.在提交检查我的工作和正确组装提交消息之前,我总是做一个git diff.通常我会重命名/移动文件,这也需要在引用某些重命名/移动文件的文件中进行一些路径更改.
我的问题是,为了显示已重命名然后修改的文件的差异,git diff还会为已重命名但未修改的文件弹出一堆融合窗口.这可能非常烦人.如何让git diff跳过重命名但未修改的文件?当我以更清晰的方式键入git status时,我将看到所有列出的文件被重命名/移动,因此我不希望弹出窗口中的相同文件与git diff.
我遇到了同样的问题,并想出了一个别名来解决这个问题(我正在使用 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') #"
Run Code Online (Sandbox Code Playgroud)
如何使用:
difftoolr commit1..commit2 -M
Run Code Online (Sandbox Code Playgroud)
(更多示例请参见底部)
怎么运行的:
假设您有三个已重命名的文件。其中之一的内容实际上已更改(因此您想使用 difftool 检查它),但其他两个除了路径或名称之外是相同的(并且您想忽略它们)。
(different) path/file.old -> newPath/file.new
(identical) path/fileB.old -> newPath/fileB.new
(identical) path/fileC.old -> newPath/fileC.new
Run Code Online (Sandbox Code Playgroud)
别名的作用是生成显式排除fileB和的路径规范fileC,即那些尽管重命名但内容未改变的文件。
换句话说,我们正在生成这些文件规范:
-- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new
Run Code Online (Sandbox Code Playgroud)
请注意(可能是最棘手的)部分:旧文件路径和新文件路径必须都明确排除。
为此,我们发布了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
Run Code Online (Sandbox Code Playgroud)
在所有情况下,“比较的双方”(提交、--cached 或其他)必须指定为第一个参数。例如git difftoolr2 -M HEAD --cached不会工作(因为-M首先)。
[alias]
# takes no parameter: sample usage: git difftoolr0 -M
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') #"
# takes 1 parameter in first position: sample usage: git difftoolr1 HEAD~1..HEAD -M
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') #"
# takes 2 parameters in first positions: sample usage: git difftoolr2 HEAD --cached -M
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') #"
Run Code Online (Sandbox Code Playgroud)
最后,BeyondCompare 可能也适合您(和我的)的需求。
它可以轻松地将并排差异切换为“非结构化”差异。
后者剥离文件夹并只留下名称。如果文件名相同(但路径可能不同),则它们被视为同一文件的两个版本(例如path/file.png和newPath/file.png)。在这种情况下,如果内容没有改变,可以使用上部栏上的按钮轻松省略它们。
如果发生“命名”冲突(比较同一侧的多个文件具有相同的名称,在不同的路径下),它会只选择其中一个进行比较,而忽略其他的。