我创建了一个简单的git repo来说明我的问题,可以在GitHub上找到:https://github.com/smileyborg/EvilMerge

这是回购历史记录的说明:

master          A---B---D---E-----G-----I
                 \     /     \         /
another_branch    ----C       \       /
                               \     /
another_branch2                 F---H

(在GitHub上的实际仓库中,D4a48c9,而I48349d。)

D 是一个“简单”的邪恶合并,其中合并提交“正确”解决了合并冲突,但也进行了不相关的“邪恶”更改,在任何一个父级中都不存在。可以通过在提交上使用git show -c来发现此合并的“邪恶”部分,因为输出包括++--(与单个+-相对)表示两个父级都不存在的更改(请参阅this answer)内容)。

I 是另一种邪恶的合并,其中合并提交“正确”解决了合并冲突(由F更改为file.txt导致与G更改发生冲突),但“evilly”放弃了对完全更改的更改。不同的文件file2.txt(有效撤消H的更改)。

您怎么知道I是邪恶合并?换句话说,您可以使用什么命令来发现I不仅可以手动解决冲突,而且无法合并应有的更改?

编辑/更新:什么是邪恶合并?

如下面的René Link所指出的,很难(也许是不可能)定义一组通用标准来标识“邪恶合并”。但是,就像Supreme Court Justice Stewart said about pornography一样,邪恶合并是您看到的东西。

因此,可能要问的一个更好的问题是:您可以在合并提交中使用什么git命令来获取仅在合并提交本身中引入的所有新颖更改的差异输出。该差异应包括:
  • 全部合并冲突解决方案(至少,如果解决方案涉及比选择 parent 一方的变更更复杂的事情)
  • 任一父级中都不存在的所有添加或删除(如D所示)
  • 在父级之一中确实存在的所有更改,但是合并提交将丢弃(如I所示)

  • 此处的目标是可以人工查看此输出,并知道合并是成功还是(偶然或恶意)“邪恶”的,而不必重新查看所有先前查看的更改(例如FH) )(已集成到合并中)。

    最佳答案

    最简单的方法是使用无需人工干预即可自动解决冲突的合并来区分冲突解决的结果。任何自动分辨率都将被忽略,因为它们的解析方式完全相同。

    我看到了两种可视化可能的“邪恶”决议的方法。如果要将其添加到脚本中,请在不需要查看输出的所有行的末尾添加&> /dev/null

    1)使用两个单独的差异,一个优先于第一个父对象,另一个优先于第二个父对象。

    MERGE_COMMIT=<Merge Commit>
    git checkout $MERGE_COMMIT~
    git merge --no-ff --no-edit -s recursive -Xours $MERGE_COMMIT^2
    echo "Favor ours"
    git diff HEAD..$MERGE_COMMIT
    git checkout $MERGE_COMMIT~
    git merge --no-ff --no-edit -s recursive -Xtheirs $MERGE_COMMIT^2
    echo "Favor theirs"
    git diff HEAD..$MERGE_COMMIT
    

    2)将冲突结果与仍然存在的冲突进行区分。
    MERGE_COMMIT=<Merge Commit>
    git checkout $MERGE_COMMIT~
    git -c merge.conflictstyle=diff3 merge --no-ff $MERGE_COMMIT^2 --no-commit
    git add $(git status -s | cut -c 3-)
    git commit --no-edit
    git diff HEAD..$MERGE_COMMIT
    

    08-27 11:10