重命名文件与请求请求壁球合并

时间:2020-03-03 13:27:06

标签: git git-merge-conflict

据我了解,当您在一个提交中提交重命名/移动并在另一个提交中进行修改时,git可以处理文件重命名/移动。

但是当您壁球合并您的PR分支时,该如何工作?

  1. 在功能分支中:重命名文件并提交
  2. 在功能分支中:修改文件并提交
  3. 创建PR
  4. 壁球将其合并为主人

同时,其他人已经在自己的功能分支中修改了相同的文件。

当他们将master合并到其功能分支时会发生什么?据我了解,重命名和文件修改是在主数据库中进行的同一提交(由于南瓜合并),对吗?那么git将如何处理呢?

1 个答案:

答案 0 :(得分:1)

据我了解,当您在一个提交中提交重命名/移动并在另一个提交中进行修改时,git可以处理文件重命名/移动。

是的,但是也没有。

这里的关键是Git不存储更改。 Git存储快照。换句话说,每个提交都具有源代码的完整副本。如果重命名一堆文件,不进行其他更改,然后创建新快照,则旧快照的内容将位于旧名称下,而新快照的内容将 same 包含在新名称下一组名称

如果重命名并修改文件,则旧快照在旧名称下具有旧内容,而新快照在新名称下具有新内容。

Git对git log --followgit diff --find-renames的作用是拍摄两个快照-假设一个有趣的事件在“之前”和“之后”,在这种情况下,有趣的事件是重命名-和< em>比较。在内部,已提交的文件存储为<名称,哈希ID>对(或更准确地说,是<模式,名称,哈希ID>三元组):

$ git ls-tree -r HEAD
[snippage]
100644 blob 41b718c29e1b9fc2981d7d14a3d25e69c31a3030    version.c
100644 blob 7c62e80577154d79bec050424945eb500d262a0f    version.h
100644 blob 069ee94a4d79422ea659a7ebe3923662f0626afa    versioncmp.c
100644 blob bb010f7a2b3c1090bc9c62f613cede7bbda86e97    walker.c
[snippage]

这里的blob实际上是mode的一部分的文本表示形式(100644始终是blob对象),因此这些行中的每一行都是读取< em> tree 条目,其中包含此名称和哈希ID配对。

每个文件内容的哈希ID仅基于文件数据,而不基于文件的名称。例如,无论文件名为walker.c还是funny.name,只要 content 相同,则 hash ID 将相同

因此,给定左右快照(前后),如果哈希ID 匹配,则 contents 也匹配。这样git diff --find-renames可以非常快速地查找重命名:我们只需排列所有匹配的哈希ID,然后将左侧的名称重命名为是的。

如果对文件进行了修改,则此快速重命名检测技巧无效。现在,Git必须实际提取所有左侧文件和所有右侧文件,并比较。与快速查看哈希ID的技巧不同,这实际上非常困难(要配对的文件数量为O(n 2 ))。 Git首先会尽力配对所有左侧和右侧的文件,而无需检查它们的内容,以便“可能被重命名”的文件列表尽可能小,然后只查看那些没有被重新命名的文件。已经配对。

因此,Git 可以处理这两种情况,只要内容的变化不大 ,这样相似检测器就可以将大量CPU时间消耗到通过相似性索引匹配文件-但是如果git diff跨越两次提交的事件是 just ,则执行匹配重命名查找的计算能力会大大降低重命名事件。这意味着所有哈希ID都匹配,而快速匹配代码完成了整个工作。

但是当您壁球合并您的PR分支时,该如何工作?

不是。

南瓜合并是工具。适当时使用它们。如果不适合壁球合并,请使用其他工具。

(记住,squash-merge表示运行git merge,但随后将结果提交为普通提交而不是合并提交。在命令行中,git merge --squash就像您每次都包含--no-commit选项一样,因此您必须自己运行git commit命令。GitHub上的clicky“ squash and merge”按钮不使用命令行命令,因此有点不同,但是最终获得的提交集与在命令行上完成所有这些提交一样。)