在维护分支上,我使用git mv old new
移动了整个网站的源文件夹。当时,我看到git status
显示了许多重命名,所以我继续提交并在此基础上开发工作(包括几个进一步的重命名)。
回过头来仔细看看这个提交,我可以看到在这个mv
提交中检测到了几个重命名,但不是全部,所以我的许多文件似乎都丢失了它们的历史记录。这很奇怪,因为我没有做任何修改,我的提交纯粹是目录重命名。
我已经将这个分支合并到另一个分支中,在经历了一个漫长的合并过程之后,我对所有内容进行了排序并签入。我决定检查一个文件的历史记录,只注意到它只追溯到最初的重命名。
我已经把所有这些改变都推到了远程。我一个人在这里工作,所以我只能和自己冲突。这将是一个痛苦的失去这个项目的历史上每一个文件的基础上,但它也将是一个巨大的痛苦回去重做所有这一切,包括合并。
有没有一种方法可以返回并纠正这个初始重命名,而不必经历我已经完成的巨大合并?
2条答案
按热度按时间uxh89sit1#
没有什么需要纠正的。
每个Git提交都会保存所有文件的快照。这些文件都有名称。如果你重命名一个文件并提交,然后比较新旧快照,你得到的是:
正如您所看到的,“旧快照”和“新快照”之间的区别在于旧文件
oldname.ext
已被删除,并添加了一个完全不同的新文件newname.ext
。Git对这样一个快照所做的就是 * 检测 * 重命名。对于左边的每个被删除的文件,以及右边的每个新添加的文件,Git会将名称放入一堆“潜在重命名”中。然后它看起来通过桩。在这里,只有一对名字可以配对。Git将查看旧提交中
oldfile.ext
和新提交中newfile.ext
的 contents。如果内容匹配,或者足够接近,Git会说:* 啊哈,文件被重命名了!* 而不是“删除旧文件,添加新文件”,你得到“重命名旧文件为新文件”。不同版本的Git有稍微不同的重命名检测器。主要的区别是 * 有多少名字 * 可以进入队列。极旧版本的Git的默认值是:
Modern Git默认开启了“detect renames”(检测重命名)功能,并且默认最多可检测400个名称对,最后一次提高这个上限是在Git 1.7.5中。
您可以自己进一步提高限制:有一个配置变量
diff.renameLimit
,默认使用内置的默认值。在配置文件中将其设置为您喜欢的任何值。将其设置为零会告诉Git尽可能地尝试。这意味着两个
git diff
运行,在 * 相同 * 仓库中的 * 相同 * 提交上,可以给予关于哪些文件被重命名,哪些文件被删除和添加的不同答案。在git diff
时间,您可以选择计算和显示差异的方式。底层的 commits 只有旧名称(在旧提交中)和新名称(在新提交中):这里没有任何改变,重做提交也无济于事。重要的是各种控制旋钮:diff.renames
)diff.renameLimit
)git diff
命令的-M
参数设置的。传入-M
会将diff.renames
设置为true
,即使您的配置本来是false
。git status
命令在启用重命名检测的情况下运行,相似性阈值设置为“50%相似”。没有配置或命令行旋钮来更改相似性值。直到最近,这里还没有禁用重命名检测的配置设置,但是Git 2.18添加了这个,沿着status.rename
配置设置,如release notes所述。(还有一个更高级的目录重命名检测算法,只是实验了一段时间,我认为自Git 2.18以来仍然存在,但它没有被很好地描述。从文档中看,它似乎只在合并时使用,而不是在diff中使用,这很奇怪,因为合并实际上在内部运行diff。请参阅上述发行说明中的第一个要点。)
pieyvz9o2#
这可能没有多大意义,但在我的PhpStorm IDE中,通过IDE本身重命名的文件被标记为“重命名”,通过“git mv”重命名的文件被标记为删除和重新添加:screenshot
为了将所有文件都带入一个状态,我在终端中运行: