cherry-pick
被实现为合并,合并基础是您引入的提交的父级。在没有合并冲突的情况下,这应该与生成和应用补丁具有完全相同的效果(但请参阅torek 的回答有点警告,am
理论上,哪里可能做错事)。
但是通过合并,cherry-pick
可以尝试更优雅地处理更改会发生冲突的情况。(事实上,-3
你给它的选项am
告诉它,如果需要的话,如果补丁中有足够的上下文可以这样做,它应该做同样的事情。我会在最后回到这一点。 ..)
当您应用补丁时,默认情况下,如果它更改了应用它的提交中与生成它的父提交中不同的代码块,则应用将失败。但是cherry-pick
/merge 方法将查看这些差异是什么,并从中产生合并冲突 - 因此您有机会解决冲突并继续。
作为冲突检测的一部分,cherry-pick
会进行重命名检测。例如,假设你有
o -- x -- x -- A <--(master)
\
B -- C -- D <--(feature)
然后你cherry-pick
承诺. 假设您已创建,并且您已对. 但是 commit移动到,并且 commit修改了。C
master
o
file.txt
A
file.txt
B
file.txt
my-old-file.txt
C
my-old-file.txt
更改为my-old-file.txt
inC
可能与更改为file.txt
in冲突A
;但要看到这种可能性,git 必须进行重命名检测,以便它可以找出它file.txt
并且my-old-file.txt
是“同一件事”。
您可能知道您没有这种情况,但 git 直到它尝试检测重命名时才知道。我不确定为什么在这种情况下会很耗时。以我的经验,它通常不是,但在一个添加和删除了很多路径的仓库中(在我们的示例之间 或B
在我们的示例中)它可能是。C
A
当您生成并应用补丁时,它会在假设没有冲突的情况下尝试应用补丁。只有当这遇到问题时(然后,只是因为您提供了-3
选项),它才会回退到进行合并,并进行冲突检测。只要它的第一次尝试干净地应用,它就可以跳过所有这些 - 以及任何潜在的重命名检测。
更新- 如对问题的评论中所述,如果重命名检测没有帮助并且运行缓慢,您也可以关闭它。如果您在实际上存在对合并“重要”的重命名时使用它,则可能会导致重命名检测可以解决它们的冲突。尽管我认为不应该,但我不能排除它也可能只是计算出不正确的合并结果并悄悄地应用它——这就是我很少使用此选项的原因。
对于默认的合并策略,该-X no-renames
选项将关闭重命名检测。您可以将此选项传递给cherry-pick
.
根据 torek 的评论,似乎重命名检测应该不是am
. 也就是说,我可以确认它能够正确处理合并仅适用于重命名检测的情况。在不是周五下午的时候,我会回到试图了解这件事的来龙去脉。