为什么';git是否了解我的文件夹移动操作?
通常,在git中重命名/移动文件时,会在文件暂存后将其显示为重命名操作。其他一些问题,如,表明无论我使用的是为什么';git是否了解我的文件夹移动操作?,git,rename,move,Git,Rename,Move,通常,在git中重命名/移动文件时,会在文件暂存后将其显示为重命名操作。其他一些问题,如,表明无论我使用的是gitmv还是常规移动,这都应该自动发生。然而,我今天做了一次大规模的重组,准备进行git子树拆分(基本上有一个Src文件夹,我将其拆分为Core和Main,为了记录,我使用Windows资源管理器移动文件夹,而不是git mv)。当我准备更改时(只有少数项目文件更改,没有任何源代码),几乎所有更改都显示为添加+删除,而不是重命名。我希望这只是Git扩展中的一个小故障,但当我推到githu
gitmv
还是常规移动,这都应该自动发生。然而,我今天做了一次大规模的重组,准备进行git子树拆分
(基本上有一个Src
文件夹,我将其拆分为Core
和Main
,为了记录,我使用Windows资源管理器移动文件夹,而不是git mv
)。当我准备更改时(只有少数项目文件更改,没有任何源代码),几乎所有更改都显示为添加+删除,而不是重命名。我希望这只是Git扩展中的一个小故障,但当我推到github时,它并没有变得更好。你可以在这里看到混乱:
在我执行本地git子树拆分--prefix=Core-b Core
并推送到另一个本地repo之后,似乎Core
文件夹中所有文件的历史记录都丢失了
发生什么事了?有没有办法保存所有这些移动文件的历史记录
> git version
git version 1.8.3.msysgit.0
考虑到您使用的是Windows,我的第一个怀疑是有什么东西(不管是什么,除非试图阻止它)将新行转换为CRLF,或者反之亦然,因此每一行都是不同的。我能够克隆URL,果然,有一些东西修改了CRLFs:
$ git show HEAD^ | vis | head -40
[snip]
diff --git a/Src/Baadia/ArrowheadControl.cs b/Baadia/ArrowheadControl.cs
similarity index 94%
rename from Src/Baadia/ArrowheadControl.cs
rename to Baadia/ArrowheadControl.cs
index 2e7aa5c..cdb374f 100644
--- a/Src/Baadia/ArrowheadControl.cs
+++ b/Baadia/ArrowheadControl.cs
@@ -1,18 +1,18 @@
-\M-o\M-;\M-?using System;\^M
-using System.Collections.Generic;\^M
-using System.ComponentModel;\^M
[snip]
+\M-o\M-;\M-?using System;
+using System.Collections.Generic;
[snip]
(M-o etc是一个字节顺序标记,没有改变。它删除了每行末尾的“^Ms”,回车,git确信这不仅仅是一个简单的重命名。)
编辑:现在CR-LF vs LF的源已经(某种程度上)被追踪到,并且您想要“插入”一个只执行反CR的提交 假设(根据我克隆时看到的情况)您有三个提交的序列:
... - A - B - C <-- branch
接下来,您希望清理所有文件以在离开LFs时删除CRs。在类似Unix的框中,您可以使用dos2unix
或其他任何东西,但假设zoop
命令使用-R
递归执行此操作:
zoop -R . # I'm assuming you're at the top of your work tree
现在提交结果:
git commit -am 'CRLF -> LF only' # or whatever message
提交图现在如下所示:
... - A - B - C <-- branch
\
A2 <-- HEAD
第一个git命令完全清空树和索引,第二个git命令从commitbranch~1
重新填充索引和树,也就是说commitB
。(请注意,这种形式的git checkout
不会更改分支,它只提取文件。在存储库的顶部,我们提取文件
,它递归地提取所有文件。)使用B
中的日志消息提交结果:
git commit -C branch~1
给予:
... - A - B - C <-- branch
\
A2 - B' <-- HEAD
或:
(这不允许您指定自定义消息),然后git checkout分支
返回,放弃旧的提交C
,重新登录
(您可能可以使用git cherry pick
来复制提交B
和C
,但这可能会更慢,如果被CRLF->LF更改搞混,则会失败。)
当需要对结果进行
git推送时,您必须使用强制推送,因为在github上更新branch
不会是一个快进操作(将放弃旧的B
和C
提交).奇怪的github
似乎认识到了这种行为:它将Src/Baadia/ArrowheadControl.cs→ Baadia/ArrowheadControl.cs
等。该特定文件被检测为重命名,相似性为94%。但是每一行都变了。其他文件可能低于默认的50%相似性索引,无法识别。有趣的发现!我不相信文件在现实中改变了;它们以前有\r\n
行结尾,现在仍然有。在某些地方,必须有一个将行尾更改为\n
的设置,但这种设置非常奇怪,以至于git有时会看到一种行尾,有时会看到另一种……现在需要弄清楚是什么在做这件事(msysgit本身?)。这让我想起了为什么当vim自动调整CRLF与LF时我会感到恼火。。。如果我想这样做,我会自己做:-)我很困惑。在我这里的两台主PC上,全局配置文件中设置了autocrlf=true
选项(没有本地autocrlf
设置)。这意味着签出时LF->CRLF,签入时CRLF->LF。因此,用LFs取代CRLFs并不奇怪。令人惊讶的是,这种情况通常不会发生。使用带有autocrlf=true
的特殊repo克隆,我了解到昨天在这台电脑上的提交在repo中存储了CRLF行结尾。这没有任何意义,因为autocrlf=true
所以CRLFs应该已转换为LFs。啊!嗯……现在怎么办?
git commit -C branch~1
... - A - B - C <-- branch
\
A2 - B' <-- HEAD
git update-ref -m "move to rewritten history" refs/heads/branch HEAD
git branch -f branch HEAD