如何在已移动/重命名的文件上执行git diff?


128

我使用移了一个文件git mv。现在,我想对新文件进行比较,以将其与旧文件(具有现在不存在的旧名称)进行比较。

我该怎么做呢?


4
很快(2016年6月git 2.9),简单git diff -- yourRenamedFile就足够了。请在下面
VonC

Answers:


145

您需要使用-M让git在进行差异时自动检测移动的文件。就像git diff提到的knittl那样对我不起作用。

简而言之:git diff -M应该这样做。

该开关的文档为:

-M[<n>], --find-renames[=<n>]
       Detect renames. If n is specified, it is a threshold on the similarity index 
       (i.e. amount of addition/deletions compared to the file’s size). For example, 
       -M90% means git should consider a delete/add pair to be a rename if more than
       90% of the file hasn’t changed.

7
救命!我的git差异现在好多了。1)始终使用此选项是否安全?2)我可以将此选项作为默认行为添加到我的~/.gitconfig吗?
kevinarpe

5
请注意,仅当旧文件和新文件同时出现在由处理的文件集合中时,重命名检测才起作用git diff。运行git diff -M在单个(改名)文件不报告重命名。
里昂,

1
这对我不起作用,但git log --follow -- file_after_move.txt效果很好。它显示了整个历史,包括搬迁之前的历史。有任何想法吗?我在跑步git version 2.11.0.windows.1
bouvierr

1
-C用于检测副本的选项非常有用且类似。我用它-M来查看一个diff,在该diff中我将一个文件重构为两个(两个文件的名称都不匹配原始文件)。
cp.engr

85

除了knittl编写的内容之外,您还可以始终使用:

git diff HEAD:./oldfilename newfilename

其中HEAD:./oldfilename表示相对于当前目录的最后一次提交(在HEAD中)的oldfilename。

如果没有足够新的git,则必须改用:

git diff HEAD:path/to/oldfilename newfilename

8
谢谢你 您还可以指定一个特定的承诺,而不是头部,即git diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
克里斯·布鲁姆

8
如果不清楚,您还可以指定分支名称或任何其他引用,例如:git diff branch:old/filen.name newfilename
jricher 2013年

第一种形式对我有用,如果您cd进入目录并且不要--在该commit:path对之前添加。Git在这里对语法似乎很挑剔。
dhardy

1
@dhardy <commit-ish>:<pathname>语法是一个对象标识符,有点像Git-ish;在--Git 之后只需要文件名。
JakubNarębski'16

18

使用git 2.9(2016年6月),您将不再需要添加-M。默认git diff使用-M

请参阅Matthieu Moy(提交5404c11提交9501d19提交a9276a6提交f07fc9e提交62df1e6(2016年2月25日(由Junio C Hamano合并--commit 5d2a30d中,2016年4月3日)moy
gitster

diffdiff.renames默认激活

重命名检测是一个非常方便的功能,新用户不必从文档中受益即可。

激活重命名检测的潜在异议是它有时会失败,并且有时会很慢。但是在某些情况下(例如“ git status”和“ git merge”),默认情况下已激活重命名检测,因此激活diff.renames不会从根本上改变情况。现在,重命名检测失败时,它在“ git diff”和“ git status” 之间始终失败。

此设置不会影响管道命令,因此,不会影响编写良好的脚本。

此功能的新测试在这里


1

git diff -M像其他人所说的那样激活重命名检测(并且@VonC指出,默认情况下它是从git 2.9激活的)。但是,如果变更集很大,则可能仍然会再次关闭不精确的重命名检测。Git将显示如下警告,在您正在查看的差异中很容易错过:

warning: inexact rename detection was skipped due to too many files.
warning: you may want to set your diff.renameLimit variable to at least 450 and retry the command.

在这种情况下,请按照git的建议设置配置选项,例如

git config diff.renamelimit 450

并重新运行diff命令。


0

出于某种原因,使用HEAD:./oldfilename(或绝对路径)对我不起作用,但对我却有HEAD:oldfilename用(感谢cmn):

git diff HEAD:oldfilename newfilename
git diff 2a80f45:oldfilename f65f3b3:newfilename

高温超导


也许您的git太旧了,无法理解HEAD:./oldfilename
JakubNarębski2012年

-4

只需运行git diff而无需任何参数,或git diff -- newfilename。git很聪明,可以比较正确的文件/内容(即,重命名之前的原始内容与重命名之后的更改内容)


2
git在大多数情况下绝对不够聪明。只需git mv使用单个文件,然后将暂存状态与另一个否则相同的分支进行比较,将产生“所有内容均已删除并再次重新创建” diff,除非-M使用该差异。
Reinderien 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.