将文件名重命名为旧名称会丢失Git中的历史记录

将文件名重命名为旧名称会丢失Git中的历史记录,git,Git,我的git repo中有两个文件 Editor.cs Editor2.cs 第一个文件是这个类的旧版本,我一直保留这个文件,直到我确定新版本(Editor2.cs)可以工作为止 现在,我想删除Editor.cs并将Editor2.cs重命名为Editor.cs。但是,当我在git中执行此操作时(即,在Editor.cs上执行git rm,然后在Editor2.cs上执行git mv到Editor.cs),我似乎丢失了Editor2.cs的历史记录 也就是说,当我查看(新重命名的)Editor

我的git repo中有两个文件

  • Editor.cs
  • Editor2.cs
第一个文件是这个类的旧版本,我一直保留这个文件,直到我确定新版本(Editor2.cs)可以工作为止

现在,我想删除Editor.cs并将Editor2.cs重命名为Editor.cs。但是,当我在git中执行此操作时(即,在Editor.cs上执行git rm,然后在Editor2.cs上执行git mv到Editor.cs),我似乎丢失了Editor2.cs的历史记录

也就是说,当我查看(新重命名的)Editor.cs的日志时,它会显示原始Editor.cs(而不是Editor2.cs)的历史记录

我尝试过使用git log--follow,但它仍然会显示错误文件的历史记录

对不起,如果这是混淆


谢谢

如果您想要
git日志,您可以做一些事情--跟随
来跟随您的文件。不过,它与使用git mv无关。我将描述Git是如何工作的,然后您可以决定希望做什么

事实上,当您按照建议操作时,Git不会丢失文件的历史记录。Git确实失去了通过
Git log--follow
跟踪该历史的能力。这种看似矛盾的状态是因为Git从一开始就没有任何文件的历史记录。

Git存储在存储库中的内容是一系列提交。每次提交都是所有文件的完整快照(自提交之日起)。当您运行
git log
(不带
--follow
)时,git会以某种顺序一次显示这些提交。如果顺序基于提交的时间,1将显示历史记录或至少历史记录的某个子集。但这是提交的历史,而不是文件的历史

使用
git日志--follow
告诉git:隐藏一些提交。像往常一样浏览提交历史记录,但只告诉我有关提交的信息,即此提交的前一个文件与此提交本身的区别,更改了我在命令行上命名的一个文件这不是文件历史记录;这是基于一个文件名的提交历史记录的子集。

诀窍在于,使用
--follow
,Git将自动从查找名为
new.txt
的文件切换到名为
old.txt
的文件,如果某些提交中的更改是重命名该文件。不过,这种特殊的技巧是以一种有点奇怪的方式启用的。Git使用重命名检测,在这种检测中,它比较两个提交,并尝试猜测(而不是记住)是否在这些提交中重命名了某些文件。2

为了比较父提交和子提交(连续进行两次提交),Git很好地提取了两次提交中的每一次。然后,它查看两次提交中每个提交中的所有文件名。旧提交中名为
read.me
的文件将自动假定为与新提交中名为
read.me
的文件“相同”。但是如果旧提交有一个
old.txt
,而新提交没有,而新提交有一个
new.txt
,而旧提交没有这个文件,那么对于重命名检测,至少Git会查看两个文件的内容。如果
old.txt
中的内容与
new.txt
中的内容非常相似,3git命令这些文件必须“相同”,因此,
old.txt
被重命名为
new.txt

Git在这里不查看文件名,而是查看数据.4,因此它不会检测到
Editor.cs
Editor2.cs
类似,除非内容非常相似。但更重要的是,只有当一个提交(父级)仅包含其中一个文件并使用其中一个名称时,它才会比较这两个文件的内容,然后紧接着第二个提交(子级)仅包含其中一个文件(使用另一个名称)。如果一个提交有两个文件,而另一个提交有一个文件,Git只会说该文件已添加(父级缺少+子级缺少)或已删除(父级缺少+子级缺少)

因此,要将其检测为“相同的文件但不同的名称”,您需要进行一次仅包含其中一个文件的提交,然后进行一次仅包含另一个文件的较新提交。两个文件的内容也必须足够相似。“完全相同”是最好的—找到100%相同的匹配比找到较小的匹配要快得多,在这里使用
git mv
可以保证您在更改名称下提交100%匹配的文件,而
git log--follow
保证可以检测到该文件。但是关键是让旧名称消失,新名称出现,一次提交。在您的情况下,这意味着您需要删除新文件,提交,然后:

  • 原地重命名旧文件并再次提交(进行100%匹配),然后用新内容替换旧文件内容(no name change=Git相信文件是相同的),或者

  • 删除旧文件并创建新文件并提交,这样就有了可检测的重命名,当且仅当内容50%或更相似时才会检测到

执行这两项操作之一将导致
git log--follow
检测到从新名称到旧名称的重命名,之后
git log--follow
将开始查找旧名称,并抑制不修改具有旧名称的文件的提交


1默认情况下,订单几乎(但不完全)是在中提交的订单。这其实相当复杂。添加
--topo order
强制执行严格的拓扑正确顺序,尽管给定了分支和合并,但某些提交将没有祖先/后代关系

2的一个优点