首页 > 解决方案 > 通过根据提交历史对行进行排序来合并,而不是标记冲突

问题描述

我有两个分支master和i1:

分公司master

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "3";
    std::cout << "5";
    return 0;
}

分公司i1

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "2";
    std::cout << "4";
    std::cout << "6";
    return 0;
}

合并i1时发生冲突master

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
<<<<<<< HEAD
    std::cout << "2";
    std::cout << "4";
    std::cout << "6";
=======
    std::cout << "3";
    std::cout << "5";
>>>>>>> master
    return 0;
}

每个提交都是按顺序完成的:

    std::cout << "1";
commit master
    std::cout << "2";
commit i1
    std::cout << "3";
commit master
    std::cout << "4";
commit i1
    std::cout << "5";
commit master
    std::cout << "6";
commit i1

我确实与 Meld 合并:

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "2";
    std::cout << "4";
    std::cout << "6";
    std::cout << "3";
    std::cout << "5";
    return 0;
}

是否可以要求合并工具根据提交历史自动创建合并:

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "2";
    std::cout << "3";
    std::cout << "4";
    std::cout << "5";
    std::cout << "6";
    return 0;
}

标签: gitgit-merge

解决方案


这是非常具体的,但如果以下条件为真(并且您暗示它们是):

  • 提交日期时间始终表示提交应发生的顺序。
  • 每个提交本身对一组连续的行执行相同的操作。(这可以自动化吗?)

然后,您可以使用以下算法来实现您想要的状态,而不是特定的合并策略:

  1. 首先从合并基础提交创建一个新分支:
git switch -c temp-branch `git merge-base master i1`
  1. 现在显示自合并基础以来发生的两个分支上的所有新提交。该命令git log可以接受多个分支,并将按时间倒序显示所有提交。您可以使用--reverse翻转该顺序,并从每个分支的合并基础开始隔离提交。因此,这样的事情会以正确的顺序获得您需要的提交列表:
git log `git merge-base master i1`..master `git merge-base master i1`..i1 --oneline --reverse
  1. 现在遍历该列表,并为每个提交解析出代表您的操作的更改。(在您的示例中添加新行。)以下是有关如何实现此目的的一些提示:Show changes in a commitShow only changed lines。解析更改后,您可以将此操作应用于您的文件。如本答案顶部的条件中所述,您理想的情况是自动执行此操作。

不幸的是,我相信步骤 3 的实施与您的特定用例密切相关。如果您可以简单地挑选列出的每个提交,那就太好了,但是在来自另一个分支的第一次提交时,您将遇到需要“以某种方式”解决的冲突。但至少与一次单一合并相比,每次提交的冲突解决将被简化。


推荐阅读