git diff 重命名文件

Posted

技术标签:

【中文标题】git diff 重命名文件【英文标题】:git diff renamed file 【发布时间】:2011-12-07 05:38:12 【问题描述】:

我有一个文件a.txt

cat a.txt
> hello

a.txt的内容是“hello”。

我做出承诺。

git add a.txt
git commit -m "first commit"

然后我将a.txt 移动到test 目录中。

mkdir test
mv a.txt test

然后我进行第二次提交。

git add -A
git commit -m "second commit"

最后,我编辑a.txt 改为说“再见”。

cat a.txt
> goodbye

我做了最后一次提交。

git add a.txt
git commit -m "final commit"

现在这是我的问题:

我如何区分我上次提交和第一次提交之间的a.txt 的内容?

我试过了: git diff HEAD^^..HEAD -M a.txt,但这不起作用。 git log --follow a.txt 正确检测到重命名,但我找不到 git diff 的等价物。有吗?

【问题讨论】:

我想如果你做一个'git mv a.txt test'会是一样的吗? IE 你只是重命名了文件,而不是将它移动到子目录中。 【参考方案1】:

HEAD^^HEAD 之间区别的问题是你在两个提交中都有一个 a.txt,所以只要考虑这两个提交(这是 diff 所做的),没有重命名,有一个复制和更改。

要检测副本,您可以使用-C

git diff -C HEAD^^ HEAD

结果:

index ce01362..dd7e1c6 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1 @@
-hello
+goodbye
diff --git a/a.txt b/test/a.txt
similarity index 100%
copy from a.txt
copy to test/a.txt

顺便说一句,如果您将差异限制为仅一条路径(就像您在 git diff HEAD^^ HEAD a.txt 中所做的那样,您将永远不会看到重命名或副本,因为您已经排除了除了单个路径和重命名或副本之外的所有内容- 根据定义 - 涉及两条路径。

【讨论】:

可以说提交包含多个文件更改。我如何将其缩小到单个文件的差异? @KenHirakawa 使用 -- <old-path> <new-path> ... 看我的回答。 在我的例子中,我想显示文件被重命名的提交的详细信息,但它只是显示一个文件被删除并添加了一个文件......我跑了@987654329 @ 并且它识别出文件重命名并向我展示了文件之间的差异。完美。【参考方案2】:

要区分特定文件的重命名,请使用-M -- <old-path> <new-path>-C 也可以)。

因此,如果您在最后一次提交中同时重命名了 并且 更改了文件,您可以通过以下方式查看更改:

git diff HEAD^ HEAD -M -- a.txt test/a.txt

这会产生:

diff --git a/a.txt b/test/a.txt
similarity index 55%
rename from a.txt
rename to test/a.txt
index 3f855b5..949dd15 100644
--- a/a.txt
+++ b/test/a.txt
@@ -1,3 +1,3 @@
 // a.txt

-hello
+goodbye

(添加// a.txt 行以帮助 git 检测重命名)


如果 git 没有检测到重命名,你可以用 -M[=n] 指定一个低相似度阈值,比如 1%:

git diff HEAD^ HEAD -M01 -- a.txt test/a.txt

来自the git diff docs:

-M[] --find-renames[=]

检测重命名。如果指定n,则它是相似度指数的阈值(即添加/删除的数量 与文件的大小相比)。例如,-M90% 表示 Git 应该 如果超过 90% 的文件,则将删除/添加对视为重命名 没有改变。如果没有 % 符号,则该数字将被读取为 分数,前面有小数点。即,-M5 变为 0.5,并且 因此与-M50% 相同。同样,-M05-M5% 相同。到 将检测限制为精确重命名,使用-M100%。默认相似度 指数为 50%。

【讨论】:

...当然,当更改和重命名像原始示例一样在单独的提交中时也有效:git diff HEAD^^ HEAD -M -- a.txt test/a.txt 只有当文件的内容足够接近 diff 才能得出相似度索引时。使用这两个选项(-M 和 -C)会显示 /dev/null 与 /dev/null 的差异,该文件已重命名并已完全更改(包括缩进),忽略时它甚至不会捕获它空格。【参考方案3】:

你也可以这样做:

git diff rev1:file1 rev2:file2

以你的为例,应该是

git diff HEAD^^:./a.txt HEAD:./test/a.txt

注意显式的./——否则这种格式假定路径是相对于回购根目录的。 (如果你在 repo 的根目录中,你当然可以省略它。)

这根本不依赖于重命名检测,因为用户明确说明了要比较的内容。 (因此,它在其他一些情况下也派上用场,例如在 git-svn 环境中比较不同 svn 分支之间的文件。)

【讨论】:

哦,这很好! 对于通过合并引入的附加文件更改的重命名,这是唯一对我有用的答案。谢谢! @LaneRettig 说了什么。奇怪,因为git diff dev 正确显示了有限的更改,但所有重命名检测建议都失败了,并将整个文件显示为新文件。所以这个答案有效,只是意味着你必须手动考虑重命名。【参考方案4】:

如果您的重命名提交已暂存但尚未提交,您可以使用:

git diff --cached -M -- file.txt renamed_file.txt

【讨论】:

以上是关于git diff 重命名文件的主要内容,如果未能解决你的问题,请参考以下文章

如何对移动/重命名的文件进行 git diff?

git:重命名文件并更改文件内容

git提交重命名文件

git重命名许多文件和文件夹

在 Git 中处理文件重命名

linux的git查看修改信息的问题