我的问题是在GitPython中做cherry-pick
。我找不到这个命令,并决定我必须以其他方式执行此操作。
另外,我只是对它在内部的工作方式感兴趣。
我将樱桃采摘提交A
理解为试图将A^
和A
之间的差异应用于HEAD
。但我怀疑它可以以某种方式用合并来表达。这就是我要求管道命令的原因。
我试图在 GitHub 上的 Git repo 中找到类似git-cherry-pick.sh
的东西,但除了测试和文档之外什么都找不到。
樱桃采摘是一个基本构建块,没有非基本等价物。 也就是说,没有较低级别的操作是"纯管道"。 原因是樱桃采摘与(可能,至少)有点糟糕的合并基础进行合并。
也就是说,通过适当的输入,git apply
在按git apply -3
运行时实现樱桃采摘(但git apply
也不是管道命令)。 其工作方式是使用每个git diff
中的Index:
行。Index:
行提供否则缺少的合并基信息。 不过,这里仍然有一件事是不同的,与重命名检测有关。
如果没有重命名,则两者是等效的。 这是因为合并操作与简单补丁有一个关键区别:合并有一个合并基础,我们可以从中派生两个补丁。
请考虑以下顺序:
-
Alice 和 Bob 从一个通用的 Git 存储库开始,在某些提交中
readme.txt
文件。 -
爱丽丝更改了第 10 行,以便它不是说"蜜蜂是紫色的",而是说"蜜蜂是绿色的"。 她还更改了第 9 行,使文件显示"下面的一切都很奇怪"。 (然后,当然,Alice 提交新文件。
鲍勃更改了第 10 行,使其不是说"蜜蜂是紫色的"> ,而是说"蜜蜂是绿色的",并且还添加了新的第 20 行,以便添加"潜艇爬树"的说法。
现在,如果 Alice 将 Bob 的更改作为补丁(没有Index:
行,只是一个上下文差异,例如,来自diff -U
)并将其输入到她的 Git 中,Alice 的 Git 将不知道如何处理 Bob 对第 10 行的更改。 添加第 20 行不会有问题,但"蜜蜂是绿色的"更改的上下文不匹配:它没有"奇怪"位。
另一方面,如果 Alice 将 Bob 的更改作为"可挑选的补丁"(通过运行实际的git cherry-pick
或通过获取带有Index:
行的差异并使用git apply -3
或等效项),Alice 的 Git 现在有了更多信息。 Alice 的 Git 现在不仅可以看到 Bob 更改了readme.txt
,还可以看到他开始时拥有该文件的版本。 具体来说,Index:
行具有readme.txt
的"之前"版本的 blob 哈希,并且由于 Alice 和 Bob 在同一提交中以相同版本的文件开始。 (它也有 Bob 的"after"版本,而 Alice 没有,但现在如有必要,可以构建整个"after"版本——但这是不必要的。
现在 Alice 的 Git 可以运行自己的 diff:它可以将基本版本与 Alice 的当前版本进行比较,看看 Alice 做了什么。 然后它可以将基本版本与 Bob 的版本进行比较,以获得它已经拥有的带有基础的补丁(但为什么要麻烦呢?这是它已经拥有的补丁! 现在它可以(尝试)组合这两个补丁:它看到 Bob 对第 10 行的更改是多余的——它包含在 Alice 自己的更改中——并且只关注第 20 行。 现在Alice的Git可以应用补丁了。
这就是文件的合并基础(和作用)。 重命名情况出现在 Git 可以区分整个树时(对于 Git,只有当 Git 可以区分整个树时),即它需要整体提交(或至少是附加到提交的tree
对象)。 在这里,git apply
将耗尽其深度,因为它一次处理一个文件。 (如果传入的补丁中有"重命名"指令,git am
代码可能能够处理它,但我不认为这是在 Git 中,尽管我承认最近没有看过。