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
?
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.
cherry-pick is a merge.
commit c
differs from c
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With