2010-11-08 53 views
9

在阅读git cherry-pick的手册页时,我的理解是它只需要一次提交引入的更改,然后可以在任何地方应用这些更改。我误解git cherry-pick?

所以我们可以说我有我建立了4个提交像这样一个文件:

line from commit 1 
line from commit 2 
line from commit 3 
line from commit 4 

如果我再开始另一个分支在提交1,我应该能够得到

line from commit 1 
line from commit 4 

樱桃采摘4

如果我有这个权利,那为什么它不起作用?我遇到了冲突,然后当我看到冲突时,看起来好像git试图从提交2,3,4中提取行。这是我的工作日志(跳到这里的肉看肉..):

szbwood-mbp15:proj5 bwood$ git init 
Initialized empty Git repository in /Users/bwood/work/gitplay/proj5/.git/ 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git add file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master (root-commit) 4cb9b97] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
create mode 100644 file1 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master 809d87c] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master b534ac9] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master fabc779] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
szbwood-mbp15:proj5 bwood$ git log 
commit fabc7795fb660d55a7ad5636321b6180157954f7 
Author: B 
Date: Sun Nov 7 21:58:07 2010 -0800 

    .. 

commit b534ac9d1f8139fc7ffa9479a3d0cb0fd08c9508 
Author: B 
Date: Sun Nov 7 21:57:53 2010 -0800 

    .. 

commit 809d87c24b1c2d27354d6bfcb34d3a1981cb7ae5 
Author: B 
Date: Sun Nov 7 21:57:35 2010 -0800 

    .. 

commit 4cb9b97c3cae9b9551fa039f87e2fff5624fbbe3 
Author: B 
Date: Sun Nov 7 21:57:19 2010 -0800 

    .. 
szbwood-mbp15:proj5 bwood$ git checkout 4cb9b97c3cae9b9551fa039f87e2fff5624fbbe3 
Note: checking out '4cb9b97c3cae9b9551fa039f87e2fff5624fbbe3'. 

You are in 'detached HEAD' state. You can look around, make experimental 
changes and commit them, and you can discard any commits you make in this 
state without impacting any branches by performing another checkout. 

If you want to create a new branch to retain commits you create, you may 
do so (now or later) by using -b with the checkout command again. Example: 

    git checkout -b new_branch_name 

HEAD is now at 4cb9b97... .. 
szbwood-mbp15:proj5 bwood$ git checkout -b new_branch 
Switched to a new branch 'new_branch' 

这里的肉

szbwood-mbp15:proj5 bwood$ more file1 
line from commit 1 
szbwood-mbp15:proj5 bwood$ git cherry-pick -x fabc7795fb660d55a7ad5636321b6180157954f7 
Automatic cherry-pick failed. After resolving the conflicts, 
mark the corrected paths with 'git add <paths>' or 'git rm <paths>' 
and commit the result with: 

     git commit -c fabc7795fb660d55a7ad5636321b6180157954f7 

szbwood-mbp15:proj5 bwood$ more file1 
line from commit 1 
<<<<<<< HEAD 
======= 
line from commit 2 
line from commit 3 
line from commit 4 
>>>>>>> fabc779... .. 
szbwood-mbp15:proj5 bwood$ 
+0

为什么我会发生冲突?即使我在第2次提交时启动新分支,我也会发生冲突 - 为什么在文件末尾添加一行会给我一个冲突?我认为有些东西我错过了,但我不知道它是什么 - 或者我不会错过它。 – bruce 2010-11-08 06:14:30

回答

17

这里的问题不在于Git的实际试图到插入内容从提交2和3,它是从提交4的内容交织着,从提交2和3。承诺4补丁看起来是这样的:

line from commit 1 
line from commit 2 
line from commit 3 
+line from commit 4 

(除非考虑到这看起来像一个测试用例,我猜你可能在那里没有任何行)。

因此,当git试图将该补丁应用于提交1中的文件内容时,它表示,嗯,我需要在第3行后面插入这一行。呃哦,那不是。好的,文件中的那一行在哪里?它反向工作并设法将其匹配起来,但知道有些东西是可疑的 - 它必须添加不是修补程序的一部分才能使修补程序适用的行。这里的关键思想是通过匹配边缘来应用补丁 - 补丁不只是说“添加到文件的末尾”,它说“在这条内容之后添加”。

所以它给了你一个冲突:HEAD(提交1)中的版本在这个位置没有任何东西,并且提交4中的版本有这三行。这取决于你决定这两行是否是最后一行的“一部分”,并且需要引入插入才能理解,或者它们是否与它分离,并且可以被删除。这与正常合并冲突中您将看到的完全相同。

如果您在补丁不相交的示例中尝试此操作 - 提交2和3将更改与提交4中的任何内容进行了几行更改,或者更好,与提交4中的不同文件相比 - 您会看到您的行为期待从樱桃挑选。你完全正确地理解了这个目的;你只是有一个凌乱的测试用例。

+0

啊非常感谢你的清楚,有益的答案。是的,我误解了这些补丁是如何应用的 - 我认为它只是将该行添加到“文件末尾”。我不知道如何通过边缘进行匹配 - 我猜这是必要算法的一部分,因为确定如何进行修补并不简单?我改变了我的测试用例,以便我的初始文件包含第1-3行,而第4行的樱桃选择非常整洁地没有冲突。再次感谢:-) – bruce 2010-11-08 06:28:00

+0

@bruce:我也不知道细节;重要的部分是要应用补丁,上下文必须匹配。 – Cascabel 2010-11-08 06:37:26