简体   繁体   中英

What's the difference between git merge --squash A SINGLE COMMIT and git cherry-pick that same commit?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM