cherry-picking a commit includes previous commits?
Asked Answered
Y

2

9

After finishing https://learngitbranching.js.org, I thought I got the idea of cherry-pick, but turned out that I didn't, at all.

I created a file abc.txt and made the commits like below:

(write a) ← (write b) ← (write c)[master][HEAD]

by which abc.txt became:

a
b
c

Now, making a branch from-a on (write a):

(write a)[from-a][HEAD] ← (write b) ← (write c)[master]

and cherry-picking (write c)[master], I thought that it would make abc.txt contain only a-line and c-line, i.e. like

a
c

but it actually resulted as:

a
<<<<<<< HEAD
=======
b
c
>>>>>>> 3a0882d... write c

Here my confusion is two-folded. Why does it conflict but not just adding the line(s)? Why does it contain b-line even though I cherry-picked only write c?

Yepez answered 6/5, 2018 at 16:12 Comment(3)
I think it’s because a git commit is not a “change” but a snapshot of the files?Lenora
@Lenora I kow that, but if that makes sense, I can’t understand what’s the point of cherry-pick...Yepez
I disagree with your assertion that "it didn't, at all". Git correctly noticed that the patch you are attempting to apply does not apply cleanly, and it is telling you about the conflict and asking you to resolve it. That seems like appropriate behavior.Albinaalbinism
V
10

Git is context aware and looks for the surrounding lines as well as the ones that are added/removed.

It makes sense, because git needs to know where should a change from commit be applied.

In your case, the branch from-a has the content

 a

Surrounding lines are empty.

The commit that you are trying to cherry-pick has the content like this:

diff --git a/abc.txt b/abc.txt
index 422c2b7..de98044 100644
--- a/abc.txt
+++ b/abc.txt
@@ -1,2 +1,3 @@
 a
 b
+c

Even if commit message shows a wider context around added/removed lines, git will only try to match the one line above and one line below modification. (Thanks das-g)

This means that git will try to find the line:

b

at the end of file and insert the line

c

after it.

Since on your branch from-a( current HEAD), git couldn't find the line

b

at the end of the file and therefore couldn't apply your patch cleanly, that resulted in conflict.

The text

<<<<<<< HEAD
=======
b
c
>>>>>>> 3a0882d... write c

represents the conflict at which git sees that the actual content at the end of a file is nothing, indicated by the

<<<<<<< HEAD
=======

but git expected to find the line

b

in order to add the line

c

after it, indicated by the

=======
b
c
>>>>>>> 3a0882d... write c

It is left like that for you to resolve conflict and decide how to join these 2 states.

When you have conflicts, you always look for the code between the pairs of <<<<<<< HEAD and >>>>>>>.
In between them, you will have ======= which separates the state on the current HEAD and the state that git expected after applying the patch.

Vale answered 6/5, 2018 at 16:46 Comment(0)
K
0

cherry-pick is a merge.

commit c differs from cs base commit, it adds line c.

commit a also differs from c's base commit, it removes line b.

                          file  [b]
                          ----
                          a
                          b


   file [a]                                  file [c]
   ----                                      ----
   a                                         a
                                             b
                                             c

Since the two change hunks overlap, Git presumes the affected lines might be related, since semantic entities in source code often occupy multiple lines you might be adding to an entity in one change and removing the entire entity in the other, line c might somehow be related to line b, and if you're deleting b you might not want to add c either.

Kike answered 6/5, 2018 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.