管道命令中的 git cherry-pick 等价物是什么?我如何在 GitPython 中实现它?

What is git cherry-pick equivalent in plumbing commands? How do I implement it in GitPython?

我的问题是在 GitPython 中执行 cherry-pick。我找不到此命令,因此决定必须以其他方式执行此操作。

此外,我只是对它的内部工作方式感兴趣。

我理解 cherry-picking 提交 A 是试图将 A^A 之间的差异应用到 HEAD。但我怀疑它可以以某种方式用合并来表达。这就是我要求管道命令的原因。

我试图在 Git 集线器上的 Git 回购中找到类似 git-cherry-pick.sh 的内容,但除了测试和文档外找不到任何东西。

樱桃采摘是没有非基本等价物的基本构建块。也就是说,没有"pure plumbing"这样的低级操作。原因是 cherry-pick 与一个(可能,至少)有点古怪的合并基础进行了合并。

就是说,当 运行 为 git apply -3(但 git apply 也不是管道命令)。其工作方式是在每个 git diff 中使用 Index: 行。 Index: 行提供了其他缺失的 merge base 信息。不过这里还有一点不同,与重命名检测有关。

如果没有renames,两者是等价的。这是因为合并操作与简单补丁有一个关键区别:合并有一个合并基础,我们可以从中导出两个个补丁。

考虑以下序列:

  • Alice 和 Bob 从一个共同的 Git 存储库开始,在一些提交中有文件 readme.txt

  • Alice 更改第 10 行,将 "bees are purple" 改为 "bees are green"。她还更改了第 9 行,使文件显示为 "Everything below is bizarre."(然后,当然,Alice 提交了新文件。)

  • Bob 更改了第 10 行,因此它不再说 "bees are purple",而是说 "bees are green",并且还添加了一个新的第 20 行,以便它添加了一个声明 "submarines climb trees."

现在,如果 Alice 将 Bob 的更改作为 补丁(没有 Index: 行,只是上下文差异,例如来自 diff -U)并将其输入她的 Git,Alice 的 Git 将不知道如何处理 Bob 对第 10 行的更改。第 20 行的添加没有问题,但是 "bees are green" 更改的上下文 不匹配:它没有 "bizarre" 位。

另一方面,如果 Alice 得到 Bob 的零钱 "cherry-pick-able patch"(通过 运行 实际 git cherry-pick 或通过 Index: 行并使用 git apply -3 或等效项),Alice 的 Git 现在有更多信息。 Alice 的 Git 现在不仅可以看到 Bob 更改了 readme.txt,还可以看到 他在开始时拥有的那个文件的版本 。具体来说,Index: 行具有 readme.txt 的 "before" 版本的 blob 哈希,并且由于 Alice 和 Bob 在同一提交中使用相同版本的文件开始。 (它还有 Bob 的 "after" 版本,Alice 没有,但现在如果需要可以构建整个 "after" 版本——但这是不必要的。)

现在爱丽丝的 Git 可以 运行 自己的差异:它可以将基本版本与爱丽丝的当前版本进行差异,看看爱丽丝做了什么。然后它可以将基础版本与 Bob 的版本进行比较,以获得它已经拥有的带基础的补丁(但是为什么要麻烦?那是它已经拥有的补丁!)。现在它可以(尝试)合并 这两个补丁:它发现 Bob 对第 10 行的更改是多余的——它包含在 Alice 自己的更改中——并且只集中在第 20 行。现在 Alice 的 Git可以打补丁

这就是合并库对文件的作用(和作用)。重命名案例出现在什么时候——对于 Git,只有什么时候——Git 可以区分整棵树,即,它需要 commit-as-a-整个(或至少附加到提交的 tree 对象)。这里 git apply 将 运行 超出其深度,因为它一次处理一个文件。 (如果传入的补丁中有 "rename" 指令,git am 代码可能能够处理它,但我不 认为 在 Git,虽然我承认最近没有看过。)