git cherry-pick {commit-hash}是什么意思?

6

假设我有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. 如果我想要打印“A”和“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
1个回答

6
Cherry-picking本质上是复制(影响)提交。您可以将其视为您明显的方式 - 即将要选择的提交与其父提交进行差异比较,然后将该差异应用于当前提交。但是,它比纯粹的差异和应用更加强大,因为它可以访问Git的完整合并机制。 这意味着git cherry-pick在内部实际上是一个完整的git merge,被合并的两个提交是您当前的提交 - 您的HEAD和您要挑选的提交。此操作的合并基础是您要挑选的提交的父提交。
这样做的原因是,正如您所见,如果您的HEAD提交和您要挑选的提交已更改“相同”的行,则可能会出现合并冲突。在这种情况下,您的HEAD提交添加了行print("A"),可能在文件末尾,但无论如何都在某些其他行之前。同时,您告诉Git要挑选的提交 - 提交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?


谢谢 @torek,我现在能够理解您在这里描述的方式,但是给定c3,唯一的变化是添加 print("C") 这一行。在我挑选了c3之后,我得到了冲突,类似于 ++<<<<<<< HEAD ++=======
  • print("b")
  • print("c") ++>>>>>>> f1383aa... C 我无法区分 print("b") 和 print("c") 的区别,但实际上它们是不同的,因为print("c")是在c3中添加的而print("b")不是。有没有办法改善这里的体验?
- zhihuifan
如果你将 merge.conflictStyle 设置为 diff3,那么你将会得到基础版本和两个提交版本。我发现这对于解决冲突非常有帮助。其他人则靠 mergetool 方法,因为你可以在三个版本上看到三个窗口(或者 mergetool 显示的任何窗口)。 - torek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接