I'm trying to understand the practical distinction between cherry-picking and squash-merging a single commit , if there is any. To be more precise, give the following simple situation:
-O <- master
\
A <- develop
Is there a practical difference between cherry-picking and squash-merging the single commit A into master?
A lot of answers here focus on the general difference when develop is several commits ahead of master (where the distinction is clear that cherry-picking processes a single commit and squash-merging process all commits back to a common ancestor).
What I'm trying to understand though is, is there any reason to prefer squash commit in this particular situation over the IMO easier performed cherry-pick?
Or maybe to make it more general, in the situation where develop is merely ahead of master (ie where fast-forwarding would be possible):
-O <- master
\
A-B-C <- develop
Is there a difference between cherry-picking A, B, and C (in that order) and then squashing them on master and the git merge --squash
-> resolve conflicts -> git commit
sequence?
My observation so far is that squash-merging often reports merge conflicts for the simplest change where cherry-picking doesn't. For example this trivial change in A (from O) is reported as merge conflict when squash-merging but not with cherry-picking:
<<<<<<< HEAD
allow(subject).to receive(:some_method).and_return(some_result)
=======
allow(controller).to receive(:some_method).and_return(some_result)
>>>>>>> 3s/checkout-page/develop
After resolving the conflicts the state of the working director is the same of course.
It seems cherry-picking is easier and less problematic in the short term, but I'm wondering if there are consequences down the road.
The default commit messages will differ.
Other than that, if the commit graph is what you've drawn here:
...--H--I--J <-- master (HEAD)
\
K <-- develop
the effect of merge or cherry-pick will be the same, because the actual merge base of master
and develop
is commit J
. To see this in action, use git rev-parse
and git merge-base
:
$ git rev-parse master
<some hash ID appears>
$ git rev-parse develop
<another hash ID appears>
$ git merge-base --all master develop
<the hash ID from the rev-parse master command appears again>
This merge or cherry-pick will never have any conflicts. The reason is that the parent of K
is J
, and the current commit is J
, so the merge-base / cherry-pick-parent is the current commit and one of the two diffs is empty.
Now let's suppose that the graph looks like this:
...--H--I--J <-- master (HEAD)
\
K <-- develop
This time, the merge base will be commit H
. The result should again be the same for both operations as the merge base of master
(the current commit J
) and develop
, but this time there could be merge conflicts, as the two sides of a diff will compare H
-vs- J
for the "ours" changes and H
-vs- K
for the "theirs" changes. If we and they touched the same lines of the same file, or touched lines that abut in any one file, we'll get a merge conflict.
A lot of answers here focus on the general difference when develop is several commits ahead of master...
Right: in this case, we have something more like, say:
...--H--I--J <-- master (HEAD)
\
K--L <-- develop
Here, cherry-picking commit L
makes Git do a three-way merge between the contents of K
(as the merge base), the contents of J
(as the "ours" commit), and the contents of L
(as the "theirs" commit). We therefore diff K
vs master
(ie, J
) to see what we changed, and K
vs L
to see what they changed. Git then combines these diffs and applies the combined changes to the contents of K
to produce a cherry-pick L'
.
By contrast, git merge --squash
finds commit H
as the merge base, comparing H
vs J
to find our changes, and H
vs L
to find theirs. Git then combines these changes—which are probably two different sets of changes than the cherry-pick sets—and applies the combined changes to the snapshot in H
, rather than to the snapshot in K
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.