Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I misunderstanding git cherry-pick?

Tags:

git

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.

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

If I then start another branch at commit 1, I should be able to get to

line from commit 1
line from commit 4

by cherry-picking in commit 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'

HERE'S THE MEAT

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$ 
like image 460
bruce Avatar asked Nov 08 '10 06:11

bruce


People also ask

Why you should not cherry pick?

Cherry picking has a negative connotation as the practice neglects, overlooks or directly suppresses evidence that could lead to a complete picture. Cherry picking can be found in many logical fallacies.

How do you know when your cherry pick changes?

In order to cherry-pick changes, you will need to identify your commit hashes. In order to see the commit hashes for your current branch, simply run the “git log” command with the “–oneline” option in order to make it more readable.

Should you cherry pick git?

git cherry-pick is a useful tool but not always a best practice. Cherry picking can cause duplicate commits and many scenarios where cherry picking would work, traditional merges are preferred instead.

Does git cherry pick rewrite history?

Running git rebase typically rewrites history and can appear to move entire branches around. This is likely the source of the undesired history you are seeing. In contrast, git cherry-pick replays the delta from one or more commits elsewhere in a repository's history.


1 Answers

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.)

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".

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.

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.

like image 67
Cascabel Avatar answered Oct 05 '22 23:10

Cascabel