Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a partial merge in git?

Tags:

git

git-merge

This question is inspired by the following excellent post: https://blogs.msdn.microsoft.com/oldnewthing/20180312-00/?p=98215 https://blogs.msdn.microsoft.com/oldnewthing/20180313-00/?p=98225 https://blogs.msdn.microsoft.com/oldnewthing/20180314-00/?p=98235

This post explains why cherry picking is evil and how it can be replaced with partial merge. Here is the picture: enter image description here

Its meaning is that if we need to make a change in the feature branch that will have to also be in the master branch, we do it on a patch branch and then merge it to both the feature and the master branches.

But it implies that we know beforehand that the change will have to be in the master too. The post does not explain what to do if the change is originally checked in to the feature branch and only later do we discover it has to be in the master branch as well.

What to do then? How to merge only this change to the master? No cherry picking, please.

like image 602
mark Avatar asked Sep 11 '25 13:09

mark


2 Answers

(As several people have noted, there is no such thing as a partial merge in Git.)

I am not the author of the original blog posts and cannot speak for him, but I will say that he is right in general. The inspiring example is a little silly, but this is almost inevitable when one attempts to make a simple example of why we might do something that looks complicated.

If you know in advance that some change needs to be applied to several branches (and are using Git), you can work your way back to the earliest commit at which the change can be made—which, by our definition of "be applied", is going to be before the other branches fork from this commit—and make a new branch from that point. You can then make the change and commit. This produces the patch branch (see the diagram Mr Chen shows in the third post, that you have copied into the question).

You can then merge this new branch into all the other branches, as shown here (and there).

But it implies that we know beforehand that the change will have to be in the master too.

Correct. In order to employ this strategy, we must know that this particular patch is destined to go into some set of N branches, and find a suitable ancestor commit that is contained in all of them.

The post does not explain what to do if the change is originally checked in to the feature branch and only later do we discover it has to be in [another] branch as well.

There is no perfect solution to this, but there is one that is Good Enough. It violates your complaint, though:

What to do then? How to merge only this change to the [other branch]? No cherry picking, please.

The way we do this is by identifying that ancestor commit—wherever it may be—and cherry-picking. (Sorry!) The cherry-pick creates one new commit that is solely on the patch branch. We then merge the patch branch into both branches, as if we had done the Right Thing the first time. This produces the following:

(apple)   (berry)
  M1---------M2     <-- master
 /          /
A----------P'     <-- patch
 \          \
  F1------P--F2     <-- feature
(apple)   (berry)

Note that merging patch into feature has no effect on the source tree in commit F2 on feature: the source tree in F2 matches that in the original patch P. This is true even if there are commits on feature after P, e.g.:

  M1---------M2     <-- master
 /          /
A----------P'     <-- patch
 \          \
  F1--P--Q---F2     <-- feature

If necessary, we can do the merge into feature with -s ours to avoid "undoing" some change or getting some sort of merge conflict. The point of doing this merge, into feature, is to make Git aware of the fact that the common ancestor of master and feature is now commit P'. Commit P' must exist, even if we have to create it just for this purpose. The easiest way to create it is to use git cherry-pick.

Cherry picking is a tool, not a solution. Mr Chen's blog post is pointing out that people use the tool poorly. That does not mean that the tool itself is bad!

like image 143
torek Avatar answered Sep 13 '25 06:09

torek


The excellent three-part post is now at

  • Stop cherry-picking, start merging, Part 1: The merge conflict
  • Stop cherry-picking, start merging, Part 2: The merge conflict that never happened (but should have)
  • Stop cherry-picking, start merging, Part 3: Avoiding problems by creating a new merge base
like image 42
luskwater Avatar answered Sep 13 '25 05:09

luskwater