【问题标题】:Does git revert also use the 3-way-merge?git revert 是否也使用 3-way-merge?
【发布时间】:2016-09-06 03:22:57
【问题描述】:

当我运行git revert 时,可能会发生冲突。 git 是否依赖于 3-way-merge,正如问题 merge internals(参见下表)中所描述的,也适用于 revert

还原的合并基础是什么?在What are the three files in a 3-way merge for interactive rebasing using git and meld? 中很清楚,但很难想象这是为了恢复。

A - B - C - D - C^-1

(如果我想在最后恢复C。)

【问题讨论】:

    标签: git merge revert git-revert 3-way-merge


    【解决方案1】:

    是的,有一个基地。 (旁注:自从我几年前查看它以来,这段代码已经发生了很大变化。我为我最近挑选的答案挑选了其中的一些,您已在此处链接。)

    git cherry-pickgit revert 都由相同的源文件(builtin/revert.csequencer.c)实现。

    正如您所说,棘手的部分是决定为合并基础伪造什么。在您的示例中,我们正在撤消 B-to-C 差异。这是实际的源代码(在sequencer.c 中),经过了一些精简:

    if (opts->action == REPLAY_REVERT) {
            base = commit;
            base_label = msg.label;
            next = parent;
            next_label = msg.parent_label;
            strbuf_addstr(&msgbuf, "Revert \"");
            strbuf_addstr(&msgbuf, msg.subject);
            strbuf_addstr(&msgbuf, "\"\n\nThis reverts commit ");
            strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
    
            if (commit->parents && commit->parents->next) {
                    strbuf_addstr(&msgbuf, ", reversing\nchanges made to ");
                    strbuf_addstr(&msgbuf, oid_to_hex(&parent->object.oid));
            }
            strbuf_addstr(&msgbuf, ".\n");
    } else {
    

    [这是精选案例,仅出于完整性考虑]

            const char *p;
    
            base = parent;
            base_label = msg.parent_label;
            next = commit;
            next_label = msg.label;
    

    当我们在这里输入时,commit 指向C 的数据,parent 指向B 的数据。对变量base 的赋值是设置合并基础的内容,next-vs-base 是要引入的内容。对于cherry-pick,提交的父级(可能通过-m 选择)是合并基础.对于还原,提交本身是合并基础,而父级(同样可能来自 -m)是要引入的内容。

    获得相同效果的另一种方法(多年前就是这样做的,直到最近,我认为这仍在使用)是反向应用由git format-patch 生成的提交。在这种情况下,构造的基本版本是第二个哈希(文本差异的 A..B 部分中的 B 部分):

    /*
     * This represents a "patch" to a file, both metainfo changes
     * such as creation/deletion, filemode and content changes represented
     * as a series of fragments.
     */
    struct patch {
    [snip]
        char old_sha1_prefix[41];
        char new_sha1_prefix[41];
    
    static void reverse_patches(struct patch *p)
    {
    [snip]
                swap(p->old_sha1_prefix, p->new_sha1_prefix);
    

    reverse_patches 函数在将文本提取到一系列补丁之后调用,即在从index 行中提取哈希的代码之后,将AB 部分放入旧的和新的前缀字段。然后(在reverse_patches 之后),当实际应用每个补丁时,git 使用保存的新旧 sha1 值来伪造一个 3 路合并(如果给定 git am --3way)。因此,通过反向应用文本补丁,我们将获得新文件作为基础,将原始文件作为目标,就像使用 sequencer.c 代码一样。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-27
    • 2011-04-17
    • 2018-03-22
    • 1970-01-01
    • 2017-09-09
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多