据我了解,当您在一个提交中提交重命名/移动并在另一个提交中进行修改时,git可以处理文件重命名/移动。
但是当您壁球合并您的PR分支时,该如何工作?
即
同时,其他人已经在自己的功能分支中修改了相同的文件。
当他们将master合并到其功能分支时会发生什么?据我了解,重命名和文件修改是在主数据库中进行的同一提交(由于南瓜合并),对吗?那么git将如何处理呢?
答案 0 :(得分:1)
据我了解,当您在一个提交中提交重命名/移动并在另一个提交中进行修改时,git可以处理文件重命名/移动。
是的,但是也没有。
这里的关键是Git不存储更改。 Git存储快照。换句话说,每个提交都具有源代码的完整副本。如果重命名一堆文件,不进行其他更改,然后创建新快照,则旧快照的内容将位于旧名称下,而新快照的内容将 same 包含在新名称下一组名称。
如果重命名并修改文件,则旧快照在旧名称下具有旧内容,而新快照在新名称下具有新内容。
Git对git log --follow
和git 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”按钮不使用命令行命令,因此有点不同,但是最终获得的提交集与在命令行上完成所有这些提交一样。)