git - git cherry-pick 和 git format-patch 有什么区别?是吗?
问题描述
我有时需要在我的分支中挑选一个带有特定修复的标签,并且过去常常通过
git cherry-pick tags/myfix
这行得通,但是挑选樱桃需要越来越长的时间来进行“不精确的重命名检测”。
我的预感是,这可能会更快
git format-patch -k -1 --stdout tags/myfix | git am -3 -k
事实上,事实证明,这立即应用了修复,使我的分支处于与樱桃采摘完全相同的状态。
现在我的问题是,樱桃采摘到底有什么不同?我以为樱桃采摘基本上就是这样实现的,但我一定是弄错了。
解决方案
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
. 也就是说,我可以确认它能够正确处理合并仅适用于重命名检测的情况。在不是周五下午的时候,我会回到试图了解这件事的来龙去脉。
推荐阅读
- django - 如何从管理员中排除模型表单验证
- javascript - 如何根据父组件的状态测试子组件是否呈现?
- php - 如何使用 PHP 解析站点地图 XML 内容
- api - 在实时服务器中部署 Adonisjs+Vuejs 应用程序
- java - 有没有办法从 mysql 中获取超出 ArrayList 最大大小的记录
- python - 无法在 Keras 中使用 VGG19 预测单个图像的标签
- react-native - 如果复选框的标签是“无偏好”,如何取消选中所有其他复选框?
- javascript - New Years Eve Clock won't redirect at midnight
- python - 解码以二进制模式打开的类文件对象
- python - 如何在地图上插入文本作为图标