批量重命名后发现Git Diff问题

时间:2015-04-25 01:11:18

标签: git rename instaweb

在将大量重命名应用于大型项目(略低于10,000个文件)后,使用我的Git历史遇到了很多麻烦。我已将文件从Project/src/....移至Project/src/main/java/....,从而更改了项目布局。我还在同一次提交中修改了一些移动的文件。

让我们来看一个这样的文件:

$ git logc PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java
* commit 6e7a960f99b0e6164d2713a4cbca2107034d8bbd
  Author: moffats <moffats@ec78347f-1a2b-0410-964c-a7254f1fcdc6>
  Date:   Thu Apr 23 21:24:30 2015 +0000

      merge gradle branch to the trunk

好的,看起来我们需要使用--follow告诉Git关注重命名:

$ git logc --follow PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java
...
* commit 6e7a960f99b0e6164d2713a4cbca2107034d8bbd
| Author: moffats <moffats@ec78347f-1a2b-0410-964c-a7254f1fcdc6>
| Date:   Thu Apr 23 21:24:30 2015 +0000
| 
|     merge gradle branch to the trunk
|     
...
* commit ce0c98d4b78e2f006ead16a030b3c5f0d7ec3ac0
  Author: perches <perches@ec78347f-1a2b-0410-964c-a7254f1fcdc6>
  Date:   Thu Mar 22 21:29:41 2012 +0000

      Updates for JSF 2.0 upgrade

我们走了。现在让我们比较两个版本:

$ git diff -M -l0 ce0c98d4b78e2f006ead16a030b3c5f0d7ec3ac0..HEAD PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java
diff --git a/PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java b/PINSSUserPasswordUtil/src/main/java/
new file mode 100644
index 0000000..acc4d40
--- /dev/null
+++ b/PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java
@@ -0,0 +1,186 @@
+package ca.gc.agr.pinss.userPasswordUtil;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
... etc ...

Git显然没有检测到重命名。它找不到文件的旧位置,并告诉我整个文件内容已添加。 请注意,它将现有文件与/dev/null进行比较,而不是旧文件路径,应该是:

PINSSUserPasswordUtil/src/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java

好的,我们来看看重命名的提交内容如下:

$ git show --stat=180 6e7a960f99b0e6164d2713a4cbca2107034d8bbd | grep UserPasswordReseter
 PINSSUserPasswordUtil/src/{ => main/java}/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java               |   10 +-

这看起来不错,所以这就是我被困住的地方。我可以获得差异的唯一方法是明确告诉Git过去的旧文件路径是什么

$ git diff ce0c98d4b78e2f006ead16a030b3c5f0d7ec3ac0:PINSSUserPasswordUtil/src/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java HEAD:PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java

-- a/ce0c98d4b78e2f006ead16a030b3c5f0d7ec3ac0:PINSSUserPasswordUtil/src/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java
+++ b/HEAD:PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java
@@ -29,18 +29,18 @@ public class UserPasswordReseter {
        private static final Log log = LogFactory.getLog(UserPasswordReseter.class);

        private static final String DATASOURCE_BEAN_NAME = "dataSource";
-       private static final String USER_PROPERTIES = "configuration/users.properties";
+       private static final String USER_PROPERTIES = "/users.properties";

现在我得到了我想要的东西。

那为什么我以前的'git diff -M -l0'命令不起作用?我认为这个问题也会导致Eclipse中的EGit和'git instaweb'这样的工具不再起作用,这意味着我失去了使用强大的GUI工具访问预重命名历史记录的能力。

我不确定如何解决这个问题。任何建议,将不胜感激。

git version 1.9.1

编辑:正如评论中所指出的,这个命令:

git diff -M -l0 ce0c98d4b78e2f006ead16a030b3c5f0d7ec3ac0..HEAD PINSSUserPasswordUtil/src/main/java/ca/gc/agr/pinss/userPasswordUtil/UserPasswordReseter.java

不起作用,b / c我们需要在整个存储库上运行diff,以便重命名检测工作。所以像这样的命令可以正常工作:

$ git diff -M -l0 ce0c98d4b78e2f006ead16a030b3c5f0d7ec3ac0 HEAD

当然,现在我需要在整个提交的大差异输出中查找我感兴趣的文件,但它确实省去了必须键入旧路径和新路径的麻烦。仍然远非理想,但比以前更好。

1 个答案:

答案 0 :(得分:2)

重命名检测在计算上非常昂贵(参见下一段),因此git将其限制为您配置的任何内容。如果你没有配置一个特定的值,git内置的默认值在各种版本中都有所增加(100,然后是200,现在是400)。

特别是,在比较任何两个修订版(或更确切地说,两个树)时,出现在&#34; old&#34;中的路径名称。树而不是&#34; new&#34;树提供了重命名的源候选文件,以及出现在&#34; new&#34;中的路径名。树而不是&#34; old&#34;树提供重命名的目标候选者。要检测实际的重命名,git必须将每个可能的源与每个可能的目标进行比较。

据我所知,git(目前)没有&#34;重命名的目录,文件名的尾部是相同的&#34;启发式减少列表的大小。如果这样做会对这里有很多帮助。没有它,您可以使用-l选项git diffdiff.renameLimit配置变量,尝试将重命名限制设置得非常高(根据需要设置多个路径名)。将其设置为明确的0意味着&#34;无限制&#34; (内部实际上是32767,因此并不完全无限制。)