如何在git中进行部分合并? [英] How to do a partial merge in git?

查看:347
本文介绍了如何在git中进行部分合并?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题的灵感来自以下出色的帖子: 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

这篇文章解释了为什么采摘樱桃是邪恶的,以及如何用部分合并代替它.这是图片:

其含义是,如果我们需要对功能分支进行更改,而该更改也必须位于master分支中,则在补丁分支上进行更改,然后将其合并到Feature和master分支中. /p>

但这意味着我们事先知道更改也必须在主数据库中.这篇文章没有说明如果更改最初是在功能分支中签入的,怎么办,直到后来我们才发现更改也必须在master分支中.

那该怎么办?如何仅将此更改合并到主服务器?请不要摘樱桃.

解决方案

(正如一些人所指出的那样,Git中没有部分合并之类的东西.)

我不是原始博客文章的作者,不能为他说话,但是我会说他总体上是正确的.令人鼓舞的例子有点愚蠢,但是当人们试图做一个简单的例子来说明为什么我们可能会做一些看起来很复杂的事时,这几乎是不可避免的.

如果您事先知道需要对多个分支(并使用Gi​​t)进行一些更改,则可以回到最早的可以进行更改的提交位置,根据我们对被应用",将在其他分支从该提交派生之前,然后从该点创建一个 new 分支.然后,您可以进行更改并提交.这将产生patch分支(请参见Chen先生在第三篇文章中显示的示意图,您已将其复制到问题中.)

然后可以将此新分支合并到所有其他分支中,如此处(此处)所示.

但这意味着我们事先知道更改也必须在主数据库中.

正确.为了采用这种策略,我们必须知道该特定补丁程序注定要进入一组 N 个分支,并找到所有分支中包含的合适的祖先提交.

该帖子没有说明如果更改最初是在功能分支中签入的,怎么办,直到后来我们才发现它也必须在[another]分支中.

没有完美的解决方案,但是有一个足够好的解决方案.但是,它违反了您的投诉:

那该怎么办?如何仅将此更改合并到[other分支]?请不要摘樱桃.

我们执行此操作的方法是,确定祖先的提交(无论可能在哪里)并进行精心挑选. (对不起!)cherry-pick创建了一个仅在patch分支上的新提交.然后,我们将补丁分支合并到两个分支中,就好像我们第一次完成了Right Thing一样.这将产生以下内容:

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

请注意,在feature上的提交F2中,将patch合并到feature中对源树没有影响 :F2中的源树与原始补丁中的源树匹配P.即使在feature 之后 P上有提交,也是如此,例如:

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

如有必要,我们可以使用-s ours合并到feature中,以避免撤消"某些更改或出现某种合并冲突. 合并到feature的目的是让Git意识到masterfeature的共同祖先现在已提交P'的事实.提交P' 必须存在,即使我们必须为此创建它. 创建它的最简单方法是使用git cherry-pick.

采摘樱桃是一种工具,而不是解决方案.陈先生的博客文章指出,人们对该工具的使用不佳.这并不意味着该工具本身就是不好的!

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:

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.

解决方案

(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!

这篇关于如何在git中进行部分合并?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆