git 'mv'没有将每个文件都标记为已重命名(有几个文件被删除/添加)

xxls0lw8  于 2023-05-05  发布在  Git
关注(0)|答案(2)|浏览(164)

在维护分支上,我使用git mv old new移动了整个网站的源文件夹。当时,我看到git status显示了许多重命名,所以我继续提交并在此基础上开发工作(包括几个进一步的重命名)。
回过头来仔细看看这个提交,我可以看到在这个mv提交中检测到了几个重命名,但不是全部,所以我的许多文件似乎都丢失了它们的历史记录。这很奇怪,因为我没有做任何修改,我的提交纯粹是目录重命名。
我已经将这个分支合并到另一个分支中,在经历了一个漫长的合并过程之后,我对所有内容进行了排序并签入。我决定检查一个文件的历史记录,只注意到它只追溯到最初的重命名。
我已经把所有这些改变都推到了远程。我一个人在这里工作,所以我只能和自己冲突。这将是一个痛苦的失去这个项目的历史上每一个文件的基础上,但它也将是一个巨大的痛苦回去重做所有这一切,包括合并。
有没有一种方法可以返回并纠正这个初始重命名,而不必经历我已经完成的巨大合并?

uxh89sit

uxh89sit1#

没有什么需要纠正的。
每个Git提交都会保存所有文件的快照。这些文件都有名称。如果你重命名一个文件并提交,然后比较新旧快照,你得到的是:

old snapshot       new snapshot
------------       ------------
README.md          README.md
file.ext           file.ext
oldname.ext
                   newname.ext
zfile.ext          zfile.ext

正如您所看到的,“旧快照”和“新快照”之间的区别在于旧文件oldname.ext已被删除,并添加了一个完全不同的新文件newname.ext
Git对这样一个快照所做的就是 * 检测 * 重命名。对于左边的每个被删除的文件,以及右边的每个新添加的文件,Git会将名称放入一堆“潜在重命名”中。然后它看起来通过桩。在这里,只有一对名字可以配对。Git将查看旧提交中oldfile.ext和新提交中newfile.extcontents。如果内容匹配,或者足够接近,Git会说:* 啊哈,文件被重命名了!* 而不是“删除旧文件,添加新文件”,你得到“重命名旧文件为新文件”。
不同版本的Git有稍微不同的重命名检测器。主要的区别是 * 有多少名字 * 可以进入队列。极旧版本的Git的默认值是:

  • 不检测重命名,除非被告知;
  • 最多使用100个名称对。

Modern Git默认开启了“detect renames”(检测重命名)功能,并且默认最多可检测400个名称对,最后一次提高这个上限是在Git 1.7.5中。
您可以自己进一步提高限制:有一个配置变量diff.renameLimit,默认使用内置的默认值。在配置文件中将其设置为您喜欢的任何值。将其设置为零会告诉Git尽可能地尝试。
这意味着两个git diff运行,在 * 相同 * 仓库中的 * 相同 * 提交上,可以给予关于哪些文件被重命名,哪些文件被删除和添加的不同答案。在git diff时间,您可以选择计算和显示差异的方式。底层的 commits 只有旧名称(在旧提交中)和新名称(在新提交中):这里没有任何改变,重做提交也无济于事。重要的是各种控制旋钮:

  • 是否启用了重命名检测器?(diff.renames
  • 文件名的数量限制是多少?(diff.renameLimit
  • 判断两个名称不同但内容相似但不是100%相同的文件是“同一个文件”的阈值是多少?最后一个是由git diff命令的-M参数设置的。传入-M会将diff.renames设置为true,即使您的配置本来是false

git status命令在启用重命名检测的情况下运行,相似性阈值设置为“50%相似”。没有配置或命令行旋钮来更改相似性值。直到最近,这里还没有禁用重命名检测的配置设置,但是Git 2.18添加了这个,沿着status.rename配置设置,如release notes所述。
(还有一个更高级的目录重命名检测算法,只是实验了一段时间,我认为自Git 2.18以来仍然存在,但它没有被很好地描述。从文档中看,它似乎只在合并时使用,而不是在diff中使用,这很奇怪,因为合并实际上在内部运行diff。请参阅上述发行说明中的第一个要点。)

pieyvz9o

pieyvz9o2#

这可能没有多大意义,但在我的PhpStorm IDE中,通过IDE本身重命名的文件被标记为“重命名”,通过“git mv”重命名的文件被标记为删除和重新添加:screenshot
为了将所有文件都带入一个状态,我在终端中运行:

git add .

相关问题