“ git diff”中同一行的两个版本

时间:2018-11-22 16:01:18

标签: git git-diff

切换分支后,我遇到了奇怪的行为。我执行了<SignupThirdPage previousPage={this.previousPage} onSubmit={this.handleFormSubmit.bind(this)} /> ,立即得到一个标记为已修改的文件。我运行git checkout master摆脱了它,但没有任何效果。 git reset --hard给了我这样的输出:

git diff

但是当我手动将其更改回时,会得到:

diff --git a/Project/MYClass.cs b/Project/MYClass.cs
index 4f8405e..cb8ca4c 100644
--- a/Project/MYClass.cs
+++ b/Project/MYClass.cs
@@ -170,7 +170,7 @@ namespace Project
-            Logger.Warn(message);
+            Logger.Info(message);

所以git无法确定是哪一个。为了使其更有趣,如果将其更改为完全不同的内容,则会得到:

diff --git a/Project/MyClass.cs b/Project/MyClass.cs
index cb8ca4c..4f8405e 100644
--- a/Project/MyClass.cs
+++ b/Project/MyClass.cs
@@ -170,7 +170,7 @@ namespace Project
-            Logger.Info(message);
+            Logger.Warn(message);

当我运行diff --git a/Project/MYClass.cs b/Project/MYClass.cs index 4f8405e..cb8ca4c 100644 --- a/Project/MYClass.cs +++ b/Project/MYClass.cs @@ -170,7 +170,7 @@ namespace Project - Logger.Warn(message); + Logger.Error(message); diff --git a/Project/MyClass.cs b/Project/MyClass.cs index cb8ca4c..4f8405e 100644 --- a/Project/MyClass.cs +++ b/Project/MyClass.cs @@ -170,7 +170,7 @@ namespace Project - Logger.Info(message); + Logger.Error(message); 时,我得到了:

git ls-tree -r master | Select-String "myclass.cs"

我看到并了解到发生了什么事,但是我不知道这是怎么发生的。

我知道如何解决它的残酷方式,删除本地文件并从远程获取所有信息,但是我想知道是什么原因造成的,以及如何正确解决它。

2 个答案:

答案 0 :(得分:4)

Git相信Project目录/文件夹中有两个不同的文件:

  • MYClass.cs(大写M,大写Y,大写C,小写lass.cs
  • MyClass.cs(大写M,小写y,大写C,小写lass.cs

Git分别打开每个文件名,写出该文件的内容,然后关闭它。

由于您使用的是Windows,拒绝制作两个仅在 case 中名称不同的文件,因此您的操作系统用两个文件之一覆盖,仅保留两个外壳之一。您的操作系统不会让Git在工作树中有两个文件。 Git 可以(并且确实)在 index 中都有这两个文件,因为Git的索引实际上是数据文件,而不是目录/文件夹。由于Git的提交不在索引之内,因此Git可以进行新的提交,该提交继续包含两个不同的文件,其名称仅以大小写不同。

您必须更新索引,使其仅包含一个 这样的名称,否则注定要在Windows(和MacOS)上永久解决此问题。一种简单的方法是在Linux或Unix系统上进行修复,其中索引和工作树保持同步,因为OS可以并且确实会创建两个不同的文件,其名称仅在大小写不同的情况下

最困难的方法是使用git rm --cached:给它一个您真正想要的名字。 Git将从索引中删除该文件,而完全不影响工作树。现在索引具有正确的大小写,您可以在工作树中固定大小写以使其匹配,但是在Windows上可以做到这一点-在其他系统上,通常的技巧是:

mv NameWithCASEISSUE x   # change the whole name a lot, using a safe name
mv x NameWithCaseIssue   # change it back, using the correct case this time

现在,您可以将索引版本与工作树版本进行比较,并进行可能需要的任何调整。由于只有一个索引版本将与工作树文件匹配,所以不管大小写问题(现在都没有,因为您已经仔细地使文件名大小写匹配了),您可以完成工作。

真正不幸的情况(如果我可以使用该词:-)发生在您确实要做想要两个文件名时,只是在大小写,索引和将来提交方面有所不同。没有好的工具可以解决这个问题。从理论上讲,可以围绕git update-indexgit checkout-index命令构建这样的工具,但目前尚不存在。

答案 1 :(得分:2)

Torek!你为什么偷我的答案? :-P

正如Torek所解释的(比我要详细得多),问题是您有两个不同的git文件...。但是当git使用Windows FS API时,它们都在FS上击中了同一个文件.....这就解释了整个问题。您如何解决?如果您不介意解决问题,请保留所需的真实文件和所需的内容,然后使用git rm删除另一个并提交。如果要及时修复该问题,请查看第二个文件的显示位置,通过删除该修订并重写其历史记录来进行修改。