git diff重命名/移动和修改文件,但跳过重命名/移动和相同的文件 [英] git diff renamed/moved and modified files but skip renamed/moved and identical files

查看:239
本文介绍了git diff重命名/移动和修改文件,但跳过重命名/移动和相同的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  git diff HEAD --diff-filter = R -M 

code>

与meld外部差异工具显示已被重命名/移动和修改的文件。在做提交之前,我总是先做一个git diff来检查我的工作并正确地组装提交消息。通常情况下,我会重命名/移动文件,这些文件还需要引用一些重命名/移动文件的文件中的路径更改。



我的问题是,为了显示一个已被重命名并修改的文件的差异,git diff还会弹出一堆已重命名但未修改的文件的合并窗口。这可能非常烦人。如何让git diff跳过重命名但未修改的文件?我会看到所有列出的文件被重命名/移动,当我以更清洁的方式键入git status时,所以我不想使用git diff来显示相同​​文件的弹出窗口。

解决方案

我遇到同样的问题,并提出了一个别名(我使用git 2.8.3)
$ b $

  [别名] 
difftoolr =!git difftool \$ @ \ - 。$((git diff \ $ 1 \-M100%--diff-filter = R - 仅命名& git diff \$ 1 \-M100%--diff-filter = R --name-only -R)| sed '/ * \\\(。* \\)/ :(排除)\\1 / g')#

使用方法:

  difftoolr commit1..commit2 -M 

(更多示例请参见下方)

它是如何工作的:



假设您有三个已重命名的文件。其中一个实际上已经改变了它的内容(所以你想用你的difftool来检查它),但其他两个是相同的,除了路径或名称(并且你想忽略它们)。

 (不同)path / file.old  - > newPath / file.new 
(相同)path / fileB.old - > newPath / fileB.new
(相同)path / fileC.old - > newPath / fileC.new

别名的作用是生成明确排除 fileB fileC ,即那些尽管重命名的文件内容不变。

换句话说,我们正在生成这些filespecs:

   - 。 :(排除)path / fileB.old :(排除)newPath / fileB.new:(排除)path / fileC.old :(排除)newPath / fileC.new 

注意(可能最棘手的部分):旧文件路径和新文件路径必须明确排除。



为此,我们使用以下指令发布 git diff




  • -M100%:按照重命名。这意味着git是假设一些重命名已完成,并将考虑这个信息做成对比较。该阈值为100%,它指示git考虑重新命名具有完全相同内容的文件,而不是那些被修改过的文件。
  • filter = R
    :仅列出git考虑重命名的文件,省略其他文件。 :只输出文件名,没有其他信息
  • -R :反向。在脚本的一部分中,我们交换了比较顺序(左右切换的顺序),因此它也会输出旧的文件名。例如 -R 指令将文件 newPath / fileB.new 列为 path / fileB .old

  • ... sed ... :最后我们追加排除指令 :(排除)到所有文件名的开头。



处理其他我创建了三个不同的别名(不是很高雅,我想要更灵活的东西),因此可以用它来指定不同类型的比较。

  git difftoolr0 -M 
git difftoolr1 HEAD〜1..HEAD -M
git difftoolr2 HEAD --cached -M

在所有情况下,比较的两边(提交, - 缓存或其他)必须被指定为第一个参数。例如 git difftoolr2 -M HEAD --cached 将不起作用(因为 -M 首先出现) p>

  [别名] 
#不带参数:示例用法:git difftoolr0 -M
difftoolr0 =!git difftool \$ @ \ - 。$((git diff -M100%--diff-filter = R - 仅命名& git diff -M100%--diff-filter = R --name-只有-R)| sed's / \\(。* \\)/ :(排除)\\1 / g')#

#需要1个参数第一个位置:样例用法:git difftoolr1 HEAD〜1..HEAD -M
difftoolr1 =!git difftool \$ @ \ - 。$((git diff \$ 1 \ - M100%--diff-filter = R - 仅命名& git diff \$ 1 \-M100%--diff-filter = R - 仅命名-R)| sed's / \ \(。* \\)/ :(排除)\\1 / g')#

#在第一个位置需要2个参数:示例用法:git difftoolr2 HEAD - 缓存-M
difftoolr2 =!git difftool \$ @ \ - 。$((git diff \$ 1 \\$ 2 \-M 100%--diff-filter = R - 仅命名& git diff \$ 1 \\$ 2 \-M100%--diff-filter = R - 仅命名-R) | sed's / \\(。* \\)/ :(排除)\\1 / g')#

最后,BeyondCompare可能也适合您的需求(和我的)。

它可以轻松地将并排差异转换为非结构化差异。



后者剥离文件夹并留下名称。如果文件名相同(但路径可能不同),则它们被认为是同一文件的两个版本(例如 path / file.png NEWPATH / file.png )。在这种情况下,如果内容没有改变,可以使用上面的一个按钮轻松省略。



如果发生命名冲突(有几个文件在比较的同一侧在不同的路径下具有相同的名称),它只会选择其中一个用于比较,而忽略其他的。


I'm using:

git diff HEAD --diff-filter=R -M

with the meld external diff tool to show files that have been both renamed/moved and modified. I always do a git diff before doing a commit to both check my work and to properly assemble the commit message. Often times I'll rename/move files, which will also require some path changes within files that reference some renamed/moved files.

My problem is that in order to show the diff of a file that has been renamed and then modified, git diff also pops up a bunch of meld windows for files that have been renamed, but not modified. This can be very annoying. How to get git diff to skip the renamed but not modified files? I'm going to see all those files listed as being renamed/moved when I type git status in a much cleaner way, so I don't want the pop ups for identical files with git diff.

解决方案

I'm having the same problem and came up with an alias that did the trick (I'm using 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') #"

How to use:

difftoolr commit1..commit2 -M

(see at the bottom for more examples)

How it works:

Imagine you have three files that have been renamed. One of them has its content actually changed (so you want to examine it using your difftool) but the other two are identical except for the path or name (and you want to ignore them).

(different) path/file.old  -> newPath/file.new
(identical) path/fileB.old -> newPath/fileB.new
(identical) path/fileC.old -> newPath/fileC.new

What the alias does is generating path specs that explicitly exclude fileB and fileC, i.e. those files that despite the renaming have the content unaltered.
In other words we are generating these filespecs:

-- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new

Notice the (perhaps trickiest) part: the old file path and the new file path must be both explicitly excluded.

To do so, we issue a git diff with the following directives:

  • -M100%: follow the renames. Which means that git is is assuming that some renaming was done, and will take this info into account to do pairwise comparisons. The threshold is 100%, which instructs git to consider renamed those files which have exactly the same content, but not the ones that were altered.
  • --diff-filter=R: list only the files that git considers renamed, omit the others.
  • --names-only: just output the file names, no other info
  • -R: Reverse. In one piece of the script we swap the order of comparison (sort of switching left and right sides), so it will also output the old file names. For instance the -R directive lists the file newPath/fileB.new as path/fileB.old.
  • ...sed...: and finally we append the exclusion directive :(exclude) to the beginning of all filenames.

To deal with other cases I created three different aliases (not really elegant, I'd like something more flexible) so it can be used to specify the different kinds of comparison.

git difftoolr0 -M
git difftoolr1 HEAD~1..HEAD -M
git difftoolr2 HEAD --cached -M

In all cases the "sides of the comparisons" (commits, --cached or whatever) must be specified as the first parameter(s). For instance git difftoolr2 -M HEAD --cached won't work (because -M comes first).

[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') #"

Finally, BeyondCompare may suit your needs as well (and mine).
It easily allows to switch the side-by-side diff into an "unstructured" diff.

The latter strips off the folders and leaves just the names. If the filename is the same (but the paths may differ) they are considered two versions of the same file (for instance path/file.png and newPath/file.png). In this case, if the content has not changed, they can be omitted easily using a button on the upper bar.

In case "naming" conflicts occurs (several files on the same side of the comparison have the same name, under different paths), it would choose just one of them for the comparison, and ignore the others.

这篇关于git diff重命名/移动和修改文件,但跳过重命名/移动和相同的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆