git cherry-pick和git format-patch |有什么区别? git是吗? [英] What is the difference between git cherry-pick and git format-patch | git am?

查看:503
本文介绍了git cherry-pick和git format-patch |有什么区别? git是吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有时需要在分支中挑选具有一定修复作用的标签,然后通过

I sometimes need to cherry-pick a tag with a certain fix into my branch, and used to do so via

git cherry-pick tags/myfix

这是可行的,但是进行"inexact重命名检测"的过程中采摘樱桃的时间越来越长.

This works, but cherry-picking takes an increasingly long time doing "inexact rename detection".

我的直觉是,这样做可能会更快

My hunch was that this could be faster with

git format-patch -k -1 --stdout tags/myfix | git am -3 -k

实际上,事实证明,这是立即应用此修复程序,使我的分支处于与选择樱桃完全相同的状态.

In fact, this turned out to apply the fix instantly, leaving my branch in exactly the same state as cherry-picking.

现在我的问题是,摘樱桃到底有什么不同?我以为摘樱桃基本上就是这样实现的,但我一定误会了.

Now my question is, what exactly does cherry-picking do differently? I thought cherry-picking was basically implemented as exactly this, but I must have been mistaken.

推荐答案

cherry-pick被实现为合并,合并基础是您要引入的cmomit的父级.在没有合并冲突的情况下,其效果应与生成和应用补丁的效果完全相同(但请参见 torek的答案警告,am在理论上可能做错了事情).

cherry-pick is implemented as a merge, with the merge base being the parent of the cmomit you're bringing in. In cases where there are no merge conflicts, this should have exactly the same effect as generating and applying the patch as you have (but see torek's answer for a bit of a caveat, where am could, in theory, do the wrong thing).

但是通过进行合并,cherry-pick可以尝试更优雅地处理更改冲突的情况. (实际上,您提供给am-3选项告诉它,如果需要的话,如果补丁中有足够的上下文可以执行此操作,则它应该执行相同的操作.我将回到最后一点...)

But by doing a merge, cherry-pick can try to more gracefully handle cases where changes would conflict. (In fact, the -3 option you gave to am tells it that, if need be, it should do the same thing if it has enough context in the patch to be able to do so. I'll come back to that point at the end...)

应用补丁程序时,默认情况下,如果补丁程序更改的代码块与应用补丁程序中的提交(与生成该补丁程序的父提交中的代码)不同,则应用程序将失败.但是cherry-pick/merge方法将查看这些差异是什么,并从中产生合并冲突-这样您就有机会解决冲突并继续进行下去.

When you apply a patch, by default if it changes a hunk of code that is not the same in the commit where you apply it, as it was in the parent commit from which it was generated, then the apply will fail. But the cherry-pick/merge approach will look at what those differences are, and generate a merge conflict from them - so you have the chance to resolve the conflict and carry on.

作为冲突检测的一部分,cherry-pick会重命名检测.例如,假设您有

As part of conflict detection, cherry-pick does rename detection. So for example, say you have

o -- x -- x -- A <--(master)
      \
       B -- C -- D <--(feature)

,然后您cherry-pickC提交到master.假设在o中创建了file.txt,并且在A中您对file.txt进行了修改.但是提交Bfile.txt移到my-old-file.txt,然后提交C修改my-old-file.txt.

and you cherry-pick commit C onto master. Suppose at o you created file.txt, and in A you have modifications to file.txt. But commit B moves file.txt to my-old-file.txt, and commit C modifies my-old-file.txt.

C中对my-old-file.txt的更改可能与在A中对file.txt的更改冲突;但是要查看这种可能性,git必须进行重命名检测,以便可以弄清file.txtmy-old-file.txt是同一件事".

The change to my-old-file.txt in C could conflict with the change to file.txt in A; but to see that possibility, git has to do rename detection so it can figure out that file.txt and my-old-file.txt are "the same thing".

您可能知道您没有这种情况,但是git在尝试检测重命名之前不知道.我不确定为什么在这种情况下会很费时;根据我的经验,通常不是,但是在具有许多添加和删除路径的回购中(在我们的示例中,在BCA之间).

You may know that you don't have that situation, but git doesn't know until it tries to detect renames. I'm not sure why that would be time-consuming in this instance; in my experience it usually isn't, but in a repo with lots of paths added and deleted (between B and either C or A in our example) it could be.

当您生成并应用补丁时,它会尝试在没有冲突的前提下应用补丁.仅当这遇到问题时(然后,因为您提供了-3选项),它才可以使用冲突检测进行合并.只要它的第一次尝试完全适用,它就可以跳过所有这些操作以及任何可能的重命名检测.

When you generate and apply a patch instead, it tries to apply the patch on the assumption that there is no conflict. Only if this runs into a problem (and then, only because you gave the -3 option) will it fall back to doing a merge, with conflict detection. It gets to skip all that - and any potential rename detection - as long as its first attempt applies cleanly.

更新-如对该问题的评论所述,如果重命名检测无济于事且运行缓慢,您还可以将其关闭.实际上,如果在将重命名为合并的情况下使用此名称,则在重命名检测可以解决这些冲突的地方可能会引起冲突.尽管我认为它不应该,但我不能排除它可能也只是计算出错误的合并结果并悄悄地应用它-这就是为什么我很少使用此选项的原因.

Update - As noted in comments on the question, you also can turn rename detection off if it's not helping and is running slowly. If you use this when there are, in fact, renames that "matter" to the merge, it may cause conflicts where rename detection would resolve them. Although I don't think it should, I can't rule out that it might also just calculate an incorrect merge result and quietly apply it - which is why I rarely use this option.

对于默认的合并策略,-X no-renames选项将关闭重命名检测.您可以将此选项传递给cherry-pick.

For the default merge strategy, the -X no-renames option will turn off rename detection. You can pass this option to cherry-pick.

根据torek的评论,似乎重命名检测应该是am的非问题.也就是说,我可以确认它能够正确处理合并仅适用于重命名检测的情况.我将再次尝试在不是星期五下午的某个时候来了解这个事情的来龙去脉.

Per torek's comment, it seems rename detection should be a non-issue with am. That said, I can confirm that it is able to properly handle a case where merge only works with rename detection. I'm going to return to trying to understand the ins and outs of this sometime when it's not Friday afternoon.

这篇关于git cherry-pick和git format-patch |有什么区别? git是吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆