问题描述
在阅读git cherry-pick的手册页时,我的理解是,它只需要一次提交引入的更改,然后可以在任何地方应用这些更改。
On reading the man page for git cherry-pick, my understanding is that it takes just the changes introduced by one commit, and you can then apply these changes pretty much anywhere.
假设我有一个文件构建超过4次提交,如下所示:
So let's say I have a file that I build up over 4 commits like so:
line from commit 1
line from commit 2
line from commit 3
line from commit 4
如果我然后在提交1开始另一个分支,我应该能够从提交1 $ b $到$ / $>
If I then start another branch at commit 1, I should be able to get to
line from commit 1
line from commit 4
通过提交4中的樱桃提取行
by cherry-picking in commit 4
如果我有这个权利,那为什么它不起作用?我遇到冲突,然后当我看到冲突时,看起来好像git试图从提交2,3,4中提取行。这里是我的工作日志(跳到这里是肉,看到肉...):
If I have that right, then why does it not work? I get a conflict, and then when I look at the conflict, it looks as if git is trying to pull in lines from commits 2,3,4. Here's the log of my work (skip to HERE'S THE MEAT to see the meat..):
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$
推荐答案
这里的问题并不在于git实际上试图从提交2和3中插入内容,而是来自提交4的内容与来自提交2和3的内容交织在一起。提交4的补丁看起来像这样:
The problem here isn't that git's actually trying to insert content from commits 2 and 3, it's that the content from commit 4 is intertwined with that from commits 2 and 3. The patch for commit 4 looks something like this:
line from commit 1
line from commit 2
line from commit 3
+line from commit 4
(除非这看起来像一个测试例如,我猜你可能在那里没有任何行。)
(except given that this looks like a test case, I'm guessing you may not have any lines below there.)
因此,当git试图将该补丁应用于提交1中的文件内容时,它说,嗯,我需要插入这行后面的行3。呃哦,这不是在这里。好的,文件中的那一行在哪里?它反向工作并设法将其匹配起来,但知道有些东西是可疑的 - 它必须添加不是修补程序的一部分才能使修补程序适用的行。这里的关键思想是补丁是通过匹配它们的边缘来应用的 - 补丁不只是说添加到文件的末尾,它表示在这条内容后面添加这个内容。
So when git tries to apply that patch to the content of the file in commit 1, it says, hm, I need to insert this line after the line from commit 3. Uh oh, that's not here. Okay, where was that line in the file? It works backwards and manages to match it up, but knows something's fishy - it had to add lines that weren't part of the patch to get the patch to apply. The key idea here is that patches are applied by matching up their edges - a patch doesn't just say "add to the end of the file", it says "add after this line with this content".
所以它给了你一个冲突:HEAD(commit 1)中的版本在这个位置没有任何内容,并且提交4中的版本有这三行。这取决于你决定这两行是否是最后一行的一部分,并且需要引入插入才能理解,或者它们是否与它分离,并且可以被删除。这与你在正常合并冲突中会看到的完全一样。
So it gives you that conflict: the version in HEAD (commit 1) has nothing at this spot, and the version in commit 4 has those three lines. It's up to you to decide whether those two lines are "part of" the last line, and need to be brought along for the insertion to make sense, or whether they're separate from it, and can be removed. This is exactly the same thing you'll see with normal merge conflicts.
如果你在一个修补程序不相交的例子中尝试这样做 - 提交2和修改3与提交4中的任何内容相距甚远,或者更好,与提交4中的不同文件相距甚远 - 您将看到您对樱桃挑选的期望行为。你完全正确地理解了这个目的;你只是有一个凌乱的测试案例。
If you try this on an example where the patches are disjoint - commits 2 and 3 make changes several lines away from anything in commit 4, or better yet, in different files from commit 4 - you'll see the behavior you expect from cherry-pick. You're understanding the purpose completely correctly; you just have a messy test case.
这篇关于我误解git cherry-pick吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!