git cherry-pick:手动接受冲突文件中的 "our" 或 "their" 帅哥

git cherry-pick: manually accept "our" or "their" hunks in conflicted files

我目前正在挑选一些提交到另一个(发布)分支。我在挑选时知道 --strategy-option theirs,但我担心这个选项不适合我选择的每个提交。

我更喜欢 运行 默认策略生成冲突,然后手动解决每个文件的冲突。

但是,有些文件我想批量接受所有 ourstheir 帅哥,手动操作会变得很麻烦。 有没有办法只接受冲突文件中的所有 ourstheir 帅哥?

注意:git checkout --ours/--theirs 似乎不适合进行挑选,因为它会从给定的分支中检出整个文件。我只想接受来自任一版本的有冲突的帅哥。

没有真正方便的方法来执行此操作,但您可以使用 Git 提供的工具构建一个。所需的主要工具是这个 git merge-file,它对单个文件版本的三重奏执行三向合并,即基础 + 我们的 + 他们的。它接受 --ours--theirs 选项来解决冲突,就像 -X ours-X theirs 对整体合并所做的一样,即它不只是采用我们的 file 或他们的 file,它只在冲突点使用我们或他们的文件。

这很好,但是,您从哪里获得这三个版本? Git 因合并冲突而停止,例如 main.py。在您的工作树中,main.py 包含 Git 留下的混乱,冲突行周围有 <<<<<<< ... >>>>>>> 标记。但是 git merge-file 需要三个未标记的输入文件,用于合并基础版本、"ours" 版本和 "theirs" 版本。但是这三个文件在 index! 如果文件 F 有冲突,则有一个 :1:<em>F</em> 与合并基础版本,:2:<em>F</em> 与我们的,:3:<em>F</em> 和他们的。

要获得它们,您可以使用 git showgit checkout-index。后者实际上是正确的工具:git mergetool 使用 git checkout-index,带有这个 shell 小功能:

checkout_staged_file () {
        tmpfile=$(expr \
                "$(git checkout-index --temp --stage="" "" 2>/dev/null)" \
                : '\([^ ]*\)    ')

        if test $? -eq 0 && test -n "$tmpfile"
        then
                mv -- "$(git rev-parse --show-cdup)$tmpfile" ""
        else
                >""
        fi
}

调用为 checkout_staged_file 1 main.py main.py.base,例如,它将 main.py 的阶段 1(合并基础)副本提取到 main.py.base。重复 2 和 3,以及第三个参数的合适变体,以获取所有三个文件。然后,运行git merge-file按照the git merge-file documentation.

中描述的方式在三个文件上

(有关更多信息,请参阅 the git mergetool source code。它只是一个很大的 shell 脚本,因此很容易阅读和根据自己的目的进行修改。)