当前位置: 首页 > 知识库问答 >
问题:

Git中的重复合并。它是如何计算差异的?

何华灿
2023-03-14

我一直在做一项研究,试图了解GIT合并是如何工作的。我知道有几种合并类型,如递归、octopus等。我发现resolve/recursive是最常用的。只有当有几个共同的祖先/基时,递归合并才有用。

但是,我找不到使用哪种算法(或者如何计算祖先),重复地从分支合并到主分支。

一个简单的例子。让我们用1个文件“a”创建一个空项目:

A

然后创建另一个文件“B”并提交给master

A
B

然后,我从只有1个文件“a”的第一个版本创建一个分支,并创建另一个文件“C”。所以我的分支是这样的:

A
C

然后我决定将我的分支更改合并到master,我得到:

A
B
C
A
C
D

这两个选项看起来都不正确。我试图通过使用“塑料SCM”来解决它,它有一个合并解释功能。正如它所显示的,祖先/基被用作版本“AC”,但是它仍然正确地计算了添加了多少文件(只有1而不是2)。

共有1个答案

麹培
2023-03-14

总结评论,并回答所问的问题...

>

  • Git使用一种寻找有向无环图的最低公共祖先的算法来计算一对提交的合并基。精确算法没有在任何地方描述,只要新算法产生正确的结果,它可能会改变。又见有向无环图中寻找最低公共祖先的算法?

    可能有多个LCAs。在本例中,-s resolve合并策略选择其中一个。你无法控制它选择哪一个。-s递归合并策略对它们运行Git merge,一次运行两个,类似于通过以下方式:

    commits=$(git merge-base --all $left $right)
    if len($commits) > 1
        a=$commits[0]
        for i in range(1, len(commits))
            b=$commits[i]
            a=$(git-merge-recursively-inner $a $b)
        rof
        commits=($a)
    fi
    

    无论如何,既然我们有了一个单一的合并基提交--从只找到一个LCA的LCA查找算法中,或者通过merge-recursive合并从LCA查找算法中得到的多个合并基,或者通过merge-resolve从列表中选择一个提交--我们可以看看Git merge-(recursiveresolve)实际上是如何合并文件的。它必须运行两个内部Git diff操作,每个操作都打开重命名检测器。

    文件差异引擎比较两个文件。我们把一个文件放在左边,另一个文件放在右边。在两个文件匹配的地方,diff什么也不说。在这两个文件不同的地方,差异引擎--取决于它有多好--会产生一些我们可以应用的更改集,以使左侧文件的内容与右侧文件的内容相匹配。

    为了区分一对提交,Git将一个放在左边,一个放在右边。然后它必须将这两个提交中的文件配对。Git可以在启用或不启用重命名检测器的情况下做到这一点。

    当没有重命名检测器时,情况非常清楚。左边和右边的文件是“同一文件”当且仅当它们具有相同的名称。添加重命名检测器将标识(标记为“相同”)diff左右两侧的某个文件,即使名称已经更改。

    Git现有的重命名检测器正在进行一些更改,以使其变得更好。这里不需要确切的细节:我们只需要知道它会说一些文件被重命名,“同一个”文件也被重命名,即使它们有不同的名称。其他文件自动为“相同”文件,因为它们具有相同的名称。

    • 要重命名的文件(从旧名到新名)
    • 要添加的文件
    • 要删除的文件

    另外,根据需要,对两个提交中存在的文件进行一些更改。

    给定一个合并基提交,解析和递归都以相同的方式进行:

      null

    高级操作可能会发生冲突!例如,如果我们重命名一个文件,而他们删除了它,这是一个高级冲突。如果我们和他们都重命名一个文件,这是一个冲突,除非我们都选择了相同的最终名称。如果我们和他们都删除一个文件,这与明显的结果结合得很好。

    低级别的变化也可能发生冲突。如果我们和他们都以不同的方式修改相同的行,或者如果我们的更改和他们的更改在任何一个边缘“接触”,就会发生冲突。例如,如果替换第9行和第10行(在第8行后面删除2行,在第8行后面插入2行),它们替换第11行和第12行,我们的更改就会接近。出于谨慎,称这是冲突。

    当然,如果我们和他们对相同的原始线条做同样的改变,那就不是冲突。Git只接受这些更改的一个副本。

    在组合了我们的所有更改和它们的更改之后,Git将把组合的更改应用到在合并基提交中找到的快照。如果没有冲突,结果文件可以自动提交。这是这些合并的默认操作;使用--no-commit禁止此默认提交。

    当merge-recursive使用内部合并进行合并基提交时,即使存在合并冲突,它也会强制提交结果。您无法看到它对这些冲突做了什么,除非当您的(外部)合并也有冲突时,在合并基中显示任何内容。(在本例中,文件的合并基副本在索引槽1中可用。此外,如果将merge.conflictstyle设置为diff3,冲突文件的每个工作树副本都将显示合并基文本,并配有冲突标记。)

  •  类似资料:
    • 问题内容: 我要分析一组客户。我对客户增长感兴趣,例如: 自上周以来增加了43位新客户(+ 32%) 自去年以来+12650(+ 1140%)新客户 该怎么办: 获得本周创造的客户 获取上周创建的客户 数他们 计算差异(百分比) 因此,首先,我将创建一个直方图,按周对客户进行分类: 这例如导致 然后,我只需要获取最后两个条目并计算差异,然后将其分配给buckets集合之外的字段。在Elastics

    • 问题内容: 我有这样的数据: 我想计算列之间的日期差异,并用差异替换列。我已经尝试过关于stackoverflow的相关解决方案,但是它们都不起作用。 问题答案: 您需要将该列转换为日期,然后才能与结合使用。使用 Spark 2.2 : 使用 < Spark 2.2,我们需要首先将该列转换为class :

    • 所有人。我在尝试合并两个映射时遇到了这个问题。IDE显示编译错误: 不能从静态上下文引用非静态方法 问题是,我需要将它们合并成一个新的,以不同的参数作为值,在这种情况下,我需要计算第一个映射的和第二个映射的LocalDateTime之间的差值,因此结果应该是 在行中还有一个,因为IDE认为value1和value2属于对象类型,而不是临时类型。这很奇怪,因为以前我在结果映射中选择了不正确的参数类型

    • 问题内容: 是否有任何库(第3方或内置库)来计算文本差异? 问题答案: 什么样的差异?文件差异?有array_diff()作用于数组。然后还有xdiff,它“使您能够创建和应用包含文件的不同修订版之间的差异的修补程序文件”。后者作用于文件或字符串。 编辑:我应该添加xdiff似乎尚未发布。您必须从源代码进行构建才能使用它。

    • 问题内容: 我尝试使用GIT,但是对我来说最大的问题是没有用于合并的工具。至少msysgit没有给我任何东西。如何在GIT中合并?是否有出色的工具,还是必须使用WinMerge或类似的应用程序? 我使用Java和Eclipse。 问题答案: 我建议kdiff3。安装它并放入类似的内容: 在你的 要编辑全局配置(.gitconfig): 您机器上的安装路径可能与有所不同。将上面的字符串替换为kdif

    • 问题内容: 我需要分离并计算arraylist中有多少个相同的值,并根据出现的次数进行打印。 我有一个名为digits的arraylist: 我创建了一个将每个值分开并将其保存到新数组的方法。 之后,我得到了一个名为数字的新数组。我在此数组上使用排序 和我的ArrayList看起来像这样: 它具有: 我需要根据数字的多少来打印出数字字符串,所以它看起来应该像这样:1354678290 问题答案: