如何对移动/重命名的文件进行 git diff?
Posted
技术标签:
【中文标题】如何对移动/重命名的文件进行 git diff?【英文标题】:How to do a git diff on moved/renamed file? 【发布时间】:2011-08-09 11:35:54 【问题描述】:我使用git mv
移动了一个文件。现在我想对新文件进行比较,以将其与旧文件(旧的,现在不存在的名称)进行比较。
我该怎么做?
【问题讨论】:
很快(git 2.9,2016 年 6 月),一个简单的git diff -- yourRenamedFile
就足够了。见my answer below
【参考方案1】:
只需运行git diff
,不带任何参数,或git diff -- newfilename
。 git 足够聪明,可以比较正确的文件/内容(即重命名前的原始内容与重命名后的更改内容)
【讨论】:
git 在大多数情况下绝对不够聪明。只需git mv
单个文件,然后将暂存状态与另一个相同的分支进行比较,将产生“所有内容都已删除并重新创建”差异,除非使用 -M
。【参考方案2】:
除了knittl wrote,你可以随时使用:
git diff HEAD:./oldfilename newfilename
其中HEAD:./oldfilename
表示上次提交中的旧文件名(在 HEAD 中),相对于当前目录。
如果你没有足够新的 git,你将不得不使用:
git diff HEAD:path/to/oldfilename newfilename
【讨论】:
谢谢。您还可以指定特定的提交而不是 head,即git diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
如果不清楚,您还可以指定分支名称或任何其他参考,例如:git diff branch:old/filen.name newfilename
第一种形式适用于我,如果您将cd
加入目录并且不要在commit:path
对之前添加--
。 Git 似乎对这里的语法很挑剔。
@dhardy <commit-ish>:<pathname>
语法是一个对象标识符,类似于 Git;在--
之后,Git 只需要文件名。
这种语法对我有用,其中 -M 只是将整个文件显示为已更改 - git version 2.30.1 (Apple Git-130)
。无论有没有前导./
,它都可以工作。 - 谢谢。【参考方案3】:
无论出于何种原因,使用 HEAD:./oldfilename
(或绝对路径)对我不起作用,但 HEAD:oldfilename
对我有用(感谢 cmn):
git diff HEAD:oldfilename newfilename
git diff 2a80f45:oldfilename f65f3b3:newfilename
HTH
【讨论】:
也许你的 git 太老了,看不懂HEAD:./oldfilename
?
这是最通用的答案。如果文件编辑过多,-M
似乎不起作用。【参考方案4】:
你需要使用 -M 让 git 在 diffing 时自动检测移动的文件。仅使用 knittl 提到的 git diff
对我不起作用。
很简单: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.
【讨论】:
救命稻草!我的 git diff 现在好多了。 1) 始终使用此选项是否安全? 2) 我可以将此选项作为默认行为添加到我的~/.gitconfig
吗?
请注意,重命名检测仅在新旧文件都出现在git diff
处理的文件集合中时才有效。在单个(重命名)文件上运行 git diff -M
不会报告重命名。
这对我不起作用,但git log --follow -- file_after_move.txt
效果很好。它显示了整个历史,包括搬家之前。有任何想法吗?我正在运行git version 2.11.0.windows.1
。
用于检测副本的-C
选项非常有用且类似。我将它与-M
一起使用,以查看我将一个文件重构为两个文件的差异(两个名称都不匹配原始文件)。【参考方案5】:
使用 git 2.9(2016 年 6 月),您不必再添加 -M
。 git diff
默认使用-M
。
参见Matthieu Moy (moy
)@commit 5404c11、commit 9501d19、commit a9276a6、commit f07fc9e、commit 62df1e6(2016 年 2 月 25 日)。(由Junio C Hamano -- gitster
-- 合并到commit 5d2a30d, 2016 年 4 月 3 日)
diff
:默认激活diff.renames
重命名检测是一个非常方便的功能,新用户不应该 必须深入研究文档才能从中受益。
激活重命名检测的潜在反对意见是它 有时会失败,有时会很慢。但是重命名检测是 在“
git status
”和“git merge
”等几种情况下已经默认激活,因此激活diff.renames
不会从根本上改变 情况。当重命名检测失败时,它现在一直失败 在“git diff
”和“git status
”之间。此设置不影响管道命令,因此编写良好 脚本不会受到影响。
The new tests for this feature are here.
【讨论】:
【参考方案6】: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 命令。
【讨论】:
以上是关于如何对移动/重命名的文件进行 git diff?的主要内容,如果未能解决你的问题,请参考以下文章
如何使 git-diff 和 git log 忽略新文件和已删除文件?