我正在开发一个长期运行的git分支,并且在分支历史的早期我重命名了一个文件。
我随后将更改从trunk更改回我的分支,其中包括对其原始名称下的文件的更改。在我这样做之后,当我的本地仓库看起来很干净时,当我在Github PR中查看它时,它告诉我存在合并冲突 - 特别是我已经重命名的文件已被删除,并且我可以用{修复此问题{1}} - 所以我做了这个并推送了结果,现在显示为空合并提交。
完成此操作后,连接旧文件和新文件的历史记录现已消失,在PR中,它显示新名称下的全新文件和旧名称下的已删除文件。
我已经尝试恢复“空”合并提交,但是当我这样做并尝试推送它然后没有任何推动时,我被告知“一切都是最新的”。
如何重新建立新命名的文件与原始文件之间的链接?
答案 0 :(得分:1)
这有多个答案,其中大部分都是“这里无事可做”。
第一个是你无法链接这些文件。 Git根本不跟踪目录;它只跟踪文件内容。每个提交只是一个快照:在提交1234567...
中,有一些文件集,这里有它们的内容。在另一个提交fedcba9...
中,这是一组文件及其内容。
第二个是Git 自己发现文件的相似性。当你让Git告诉你一些提交时,Git会查看该提交及其父提交。父提交有一堆文件作为快照。孩子 - 你问Git的提交 - 有另一堆文件作为快照。 Git比较了两个快照,并告诉你它们之间发现了什么不同。如果一个文件似乎已经丢失,并且似乎已经创建了另一个新文件,那么该文件可能已重命名。 Git检查!如果它找到两个完全相同但在两次提交中具有不同名称的文件,那么该文件必须已被重命名。
如果文件已从父级中删除并显示在子级中并且具有不同的内容,则可能仍会重命名该文件。在这种情况下,Git计算相似性索引。如果文件“足够相似”(默认为50%),Git会假定文件已重命名。
在某些情况下,您可以控制相似性阈值。当您要求Git使用git diff -M
为您查找重命名时,您可以指定相似性阈值:git diff -M75
表示它们必须至少相似75%,而git diff -M15
表示它们可以是只有15%的相似。
当您使用git merge
时,git会在内部运行两个 git diff
命令。两者都使用-M50%
并且没有控制旋钮可以让你改变它。如果Git在两个差异之一中检测到重命名的文件,则会记下这一点。如果Git在两个git diff
中的另一个中检测到不同的重命名或对相同文件的其他更改,则会出现修改/重命名冲突或重命名/删除冲突。请注意,这两个差异来自 merge base - Git自动为您找到的提交 - 两个分支提示提交。由您来解决任何合并冲突。
最后,通过告诉Git提交一些文件集 - 一些新的快照来完成合并。根据您在索引中保留的内容,您提交的快照就是该提交中的内容。如果从索引中删除文件,则它不在新提交中。如果你保留文件,它就在新的提交中。
你做的新提交有两个父母。一个父级是分支的前一个提示,就在您进行此新提交之前,现在是分支的一端。另一个父提交是你告诉Git合并的提交。
每当您提交Git show的提交是合并提交时,它(至少)两个父级。一些Git命令对此做了一些特别的事情,有些人只是不打算给你看一个补丁。 (特别是运行git log -p
后者:根本不显示任何内容。)合并不为空!合并有一个快照,就像任何非合并提交一样。只是将比较快照与父母双方都很棘手。一些Git命令不打扰。其他人,比如git show
,但是会产生Git所谓的组合差异,它通常会省略diff输出中的大部分甚至所有文件。
您可以拆分与-m
合并,以便显示。然后,Git会将每个父母与孩子进行比较,一次一个,并向您展示每个人的差异。其中一个差异可能会删除一个文件。
如果您看到的合并不是您想要的结果,请考虑抛弃合并提交(使用git reset
)。请注意,如果您在其他位置git push
合并结果,则会变得更加困难。