1

在将批量重命名应用于大型项目(略低于 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 工具访问预重命名历史记录的能力。

我不确定目前如何解决它。任何建议,将不胜感激。

混帐版本 1.9.1

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

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

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

$ git diff -M -l0 ce0c98d4b78e2f006ead16a030b3c5f0d7ec3ac0 HEAD

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

4

1 回答 1

2

重命名检测的计算成本很高(参见下一段),因此 git 将其限制为您配置的任何内容。如果你不配置一个特定的值,git 已经内置了在不同版本中增加的默认值(之前是 100,然后是 200,现在是 400)。

特别是,当比较任何两个修订版(或更准确地说,两棵树)时,出现在“旧”树中而不是“新”树中的路径名提供了重命名的源候选文件,而出现在“新”树而不是“旧”树提供重命名的目标候选者。要检测实际的重命名,git 必须将每个可能的来源与每个可能的目的地进行比较。

据我所知,git(当前)没有“重命名目录,文件名的尾部部分相同”的启发式方法来减少列表的大小。如果这样做的话,这将有很大帮助。-l如果没有它,您可以尝试使用to 选项git diffdiff.renameLimit配置变量将重命名限制设置得非常高(根据需要设置尽可能多的路径名) 。将其设置为显式0意味着“无限”(内部实际上是 32767,因此不是无限的)。

于 2015-04-25T01:27:35.737 回答