是什么让g和diff中的C和R过滤器--diff-filter = CR命令?

时间:2014-02-11 09:03:28

标签: git

我无法理解git diff-filter的“复制”和“重命名”是什么意思,根据这个答案:https://stackoverflow.com/a/6879568/2039203。当我重命名/移动某个文件时,该文件被处理为“已添加”和“已删除”。

所以问题是:我应该怎样做才能使用以下两个命令过滤一些文件?我是否需要此过滤器选项来获取添加/删除的文件列表?

git diff --diff-filter=C --name-only

git diff --diff-filter=R --name-only

2 个答案:

答案 0 :(得分:2)

由于默认情况下不启用复制和重命名检测,因此您需要更多一点。

试试这个:

git init example
cd example
echo foo > foo.txt
echo baz > baz.txt
git add .
git commit -m "add foo and baz"
cp baz.txt other-baz.txt
git mv foo.txt bar.txt
git add other-baz.txt

此时,您应该在git status -s中看到类似的内容:

## master
R  foo.txt -> bar.txt
A  other-baz.txt

这里要注意两件事:git status确实重命名检测,但它没有进行复制检测。因此它会告诉您重命名,但它会将副本显示为添加。此外,更改暂存。因此普通git diff不会显示任何内容。

要查看--diff-filter=C--diff-filter=R是否正常工作,您需要告诉git diff进行复制和重命名检测,并且需要让它查看暂存区域(称为“索引“在git文档中)。试试这个:

$ git diff --staged -C -C --diff-filter=C --name-only
other-baz.txt

$ git diff --staged -C --diff-filter=R --name-only
bar.txt

在这种情况下,副本需要指定-C两次以使Git在执行复制检测时查看先前的提交(因为它是先前提交的文件的副本)。您还可以使用--find-copies-harder启用此行为。

答案 1 :(得分:1)

如果文件通过“相似性测试”,

git diff会将文件显示为“重命名”。为了确保它正在发生,请指定-M选项(我将在下面执行此操作)。 1

$ mkdir /tmp/temprepo && cd /tmp/temprepo && git init
$ cat << end > file
> Here is some text for a file.
> We want it to be long enough
> that renames and copies can
> be detected fairly easily.
> If we put ten lines into the
> file, then each percent of
> similarity is one tenth of
> each of the lines, i.e., each
> line represents 10% similarity
> to the earlier file.
> end
$ git commit -m initial
[master (root-commit) 842824a] initial
 1 file changed, 10 insertions(+)
 create mode 100644 file
$ git mv file newname
$ git diff --cached --name-status
R100    file    newname

让我们继续并提交这个,以便我们可以git diff两次提交,而不是提交和索引:

$ git commit -m B
[master a2380eb] B
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename file => newname (100%)

看看它做了什么:

$ git diff --name-status -M HEAD^ HEAD
R100    file    newname

现在让我们做一个小改动:

$ ed newname
279
9s/10/about 10/p
line represents about 10% similarity
w
285
q
$ git commit -a -m C
[master 57fce41] C
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git diff --name-status -M HEAD~2 HEAD
R087    file    newname

--name-status(初始提交)与最新提交之间的差异(选择HEAD~2模式)现在显示文件file仅重命名为newname %相似度,而不是100%的相似度(如HEAD~2HEAD~1之间所见)。 2

要查看副本,您通常必须使用git diff和/或-C运行--find-copies-harder

您可以在-M(和-C)之后控制使用数值检测重命名(和副本)的相似文件的位置,例如-M90%导致上述{{1}将重命名视为添加 - 删除对:

git diff --name-status

$ git diff --name-status -M90% HEAD~2 HEAD D file A newname 选项也会影响重命名检测,-B设置git configdiff.renameLimit也会影响重命名检测(请参阅文档)。完全打败重命名检测 - 这使得在许多情况下用diff.renames编写git钩子脚本变得容易很多 - 使用--diff-filter


1 如果在git config中将--no-renames设置为diff.renames,则此相似性测试默认为“50%相似” {{1 }}),但“仅精确匹配”如果不是(由于git如何存储数据,完全匹配检测很容易)。在编写示例时,我忘记了我默认启用了重命名检测。

2 之前,我们使用过truegit config --global diff.renames true,但从那时起我们添加了提交HEAD^,因此初始提交现在为HEADC