git cherry-pick {commit-hash} 做什么?

what does git cherry-pick {commit-hash} do?

假设我有 3 个提交顺序

c1
+ print("A")

c2
+ print("B")

c3
+ print("C")

然后我在 c1 签出一个新分支。

git checkout -b br c1

然后我挑选 c3。

git cherry-pick c3.

我要的是文件有

print("A")
print("C") 

-- 我只选择 c3,c3 只添加行 print("C")

但事实是我遇到了冲突,结果是

print("A")
++<<<<<<< HEAD
++=======
+ print("B")
+ print("C")
++>>>>>>> f1383aa... C

我的问题是: 1.为什么会冲突? 2.我要print("A")和print("C")怎么办?

我也试过

git diff C^1 .. C > 1.patch
git apply 1.patch

我得到了

zhifan@zhifandeMacBook-Pro ~/g/demo> git apply 1.patch
error: patch failed: 1.py:1
error: 1.py: patch does not apply

Cherry-picking 本质上是复制 提交(的效果)。您可以按照您显然的方式来思考它——即, 比较要选择的提交及其父提交,然后将该差异应用于当前提交。但是,它比单纯的比较和应用更强大,因为它可以访问 Git 的完整 合并机制 .

这意味着 git cherry-pick 在内部确实是一个完整的 git merge,合并的两个提交是您当前的提交——您的 HEAD——以及您现在的提交采摘樱桃。此操作的 merge base 是您正在挑选的提交的父项。

这样做的原因是,如您所见,如果您的 HEAD 提交和您的提交都是 cherry-,您可能会遇到 合并冲突 采摘已更改 "the same" 行。在这种情况下,您的 HEAD 提交添加了行 print("A"),可能在文件末尾,但无论如何都在其他行之前。同时,您告诉 Git cherry-pick 的提交——提交 c3——在同一位置 添加行 print("C") (在文件末尾,或在同一现有行之前)。 Git 不知道将添加的 print 放在哪里,所以它声明了一个冲突并让 选择了正确的答案。

解决方法很简单:在你的编辑器中打开冲突的文件并调整它以包含冲突的正确解决方案,然后写出来并在文件上使用 git add 这样你就可以 运行 git cherry-pick --continue 完成樱桃采摘过程。或者,如果您愿意,可以使用合并工具获取所有三个输入文件(基础、"ours" 或 HEAD,以及 "theirs" 或 c3 的版本)并以此方式解决冲突。

有关 cherry-pick 的更多信息,请参阅 What does cherry-picking a commit with git mean?