手动合并后如何规范来自合并请求的合并 [英] How to normalize a merge from a pull request after doing a manual merge

查看:88
本文介绍了手动合并后如何规范来自合并请求的合并的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

共有三个分支:dev,master和release.
该流程是从dev到master以及从master到release的合并.
生产中引用了发布分支.
(基本上,源通过git pull反映在生产中.)

There are three branches: dev, master and release.
The flow is to merge from dev to master and from master to release.
The release branch is referenced in production.
(Basically, the source is reflected in production by git pull.)

我正在使用Gitea,类似于Github.
基本上,我通过请求请求合并到每个分支中.

I'm using Gitea, which is similar to Github.
Basically, I'm merging into each branch with a pull request.

有一天,我被要求只在发布分支上反映一个特定的提交.
那时,我使用cherry-pick来将特定的提交从master分支合并到release分支.
这时候,我从命令行手动合并了.

One day, I was asked to reflect only a particular commit on the release branch.
At that time, I used cherry-pick to merge specific commits from the master branch to the release branch.
At this time, I manually merged from the command line ...

然后释放.

然后,几天后,我将master分支合并到release分支中,以释放所有提交.
这时候,我从命令行手动合并了.

Then, a few days later, I merged the master branch into the release branch to release all the commits.
At this time, I manually merged from the command line ...

当前问题是如果没有通过请求请求,该怎么办.
我可以从拉请求中将开发人员合并到主人员.
但是通过拉取请求从主服务器合并到释放服务器存在一些冲突.

And the current issue is what to do if the pull request doesn't pass.
I can merge from dev to master from pull request.
But there are some conflicts for merging from master to release by pull request.

上次,我手动解决并合并了发布分支中的冲突,因此dev,master和release分支具有相同的内容.
之后,开发人员致力于开发.
之后,我能够将开发人员的拉取请求合并到母版中.(无冲突)
从主服务器的拉取请求合并到发布将导致冲突.

Last time, I manually resolved and merged the conflicts in release branch, so the dev, master, and release branches had the same content.
After that, development was committed to dev.
After that, I was able to merge from a pull request from dev to master. (No conflict)
And merging from a pull request from master to release will result in conflicts.

我认为原因是发布分支中先前手动合并的结果.
手动合并后如何从合并请求中归并?

I think the cause is the effect of the previous manual merge in release branch.
How to normalize a merge from a pull request after doing a manual merge?

推荐答案

关于并行分支和合并的简短(hah)文章

您遇到的情况是所使用的Git流的结果,其中有两个(在您的情况下为三个)持久并行分支.只有当您一致地合并时,该流才有效并完全从一个分支到另一个分支的一个方向.如果您颠覆了该拓扑,则可能会让自己陷入潜在的冲突.

A short (hah) essay about parallel branches and merges

The situation you're experiencing is a result of the Git flow you are using, where there are two (in your case, three) persistent parallel branches. That flow only works if you merge consistently and fully in one direction from one branch to the other. If you subvert that topology, you are letting yourself in for potential conflict.

要了解此拓扑的工作原理,您必须问自己:什么是合并?是尝试同时重建和执行多组更改(通常是两组更改)的尝试.

To understand how this topology works, you have to ask yourself: What is a merge? It is an attempt to reconstruct and perform multiple sets of changes simultaneously (usually, exactly two sets of changes).

让我们演示.在这里,我准备了刚才描述的标准拓扑中的存储库.在工作树中(以及在仓库中)只有一个文件,并且只有一行,我在每次提交时都会对其进行更改.一开始,该行显示为"a":

Let's demonstrate. Here I've prepared a repo in the standard topology I just described. There is just one file in the working tree (and in the repo), and it has just one line, which I am changing on every commit. At the start, that line says "a":

*   086cbed (HEAD -> master) merged once again
|\  
| * 82abd8a (br) now it is d
* |   ec0397a merged branch again
|\ \  
| |/  
| * 2546392 changed it to c
* |   f6535d4 merged branch
|\ \  
| |/  
| * c9fcf16 changed a to b
|/  
* a014c37 start

我有两个分支,分别是 master br .我一直在研究 br 并将 br 合并到 master 中.合并时,我说-no-ff 以便每次都获得真正的合并提交;这很重要.

I have two branches, master and br. I keep working on br and merging br into master. When I merge, I say --no-ff so as to get a true merge commit each time; that's important.

现在,我一次又一次地更改同一单行文件的同一行,但是没有合并冲突.为什么?因为 master 对更改没有任何贡献.

Now, I am changing the same line of the same one-line file over and over, but there is no merge conflict. Why? Because master is not making any contribution to the changes.

当我们要求将 br 合并为 master 时,让我们置身于Git的脑袋.Git查看 br 上发生的情况,并发现文件的第一行已更改;并且还查看了 master 上发生的情况,并发现没有任何变化!因此,Git自言自语:好吧,同时进行这两个 更改很容易;br-bone-done-on-brone."

Let's put ourselves inside Git's head when we ask to merge br into master. Git looks at what happened on br and sees that the first line of the file changed; and it also looks at what happened on master and sees that nothing changed! So Git says to itself: "Well, it's easy to enact both of those changes simultaneously; stuff-done-on-br plus nothing equals stuff-done-on-br alone."

因此,Git通过在 master 上执行在 br 上执行的操作来同时制定这两个更改集,即,它更改文件的那一行以匹配它的内容.在 br 上.

So Git enacts both of those change sets simultaneously by doing on master what was done on br, namely, it changes that one line of the file to match what it is on br.

现在,在继续之前,我应该先说说改变"的内容.方法.特别是,何时更改?这实际上至关重要,并且是整个故事的关键.

Now, before I go on, I should say something about what "changed" means. In particular, changed since when? This is actually crucial and is the key to the entire story.

当您要求Git进行合并时,Git会立即开始考虑分支上次相遇的点 (或最后发散的)的变化,具体取决于哪种方式你看看).这称为合并基础 —实际上,Git有一个 merge-base 命令,告诉您它在哪里.

When you ask Git to do a merge, Git immediately starts thinking about the changes from the point where the branches last met (or last diverged, depending on which way you look at it). This is called the merge base — and in fact, Git has a merge-base command that tells you where it is.

例如,查看上面的图表,让我们重构上一次合并(086cbed)的逻辑.返回上一步.假设我们分别位于82abd8a(在 br 上)和ec0397a(在 master 上),并且我们要求将 br 合并到 master .Git计算出这些分支最后一次见面(或分叉)于2546392.这就是合并的基础.

For example, looking at the chart above, let's reconstruct the logic of the last merge (086cbed). Go back one step. Suppose we are at 82abd8a (on br) and ec0397a (on master) and we ask to merge br into master. Git works out that those branches last met (or diverged) at 2546392. That's the merge base.

再看一下图形,您可以看到Git如何知道这一点.ec0397a是真正的合并提交,因此2546392作为其父项之一;同时82abd8a是正常提交​​,它的祖先2546392(在此图中为其直接父级).

And looking at the graph, you can see how Git knows this. ec0397a is a true merge commit, so has 2546392 as one of its parents; and meanwhile 82abd8a is a normal commit, and it has 2546392 as its ancestor (its direct parent, in this graph).

因此,这是此拓扑的值.为您提供与真正的合并保持合并的机会,以便每次都有合并提交,并且只要目标分支(此处为 master )从未对历史做出任何其他贡献,您将始终能够合并而不会发生冲突.

So that is the value of this topology. Providing you keep merging with true merges, so that there is a merge commit every time, and provided the target branch (here, master) never makes any other contribution to the history, you will always be able to merge without conflict.

好的,现在让我们说您通过直接在 master 上进行独立提交来扭曲拓扑.同时,您继续进行 br 的工作,最终尝试将通常将 br 合并到 master 中.现在有冲突的可能性,因为两个分支都在做出贡献性变化,而这些贡献可能会冲突.

Okay, so now let's say you pervert the topology by making an independent commit directly on master. Meanwhile you go on working on br, and eventually you try to make your usual merge of br into master. Now there is a likelihood of conflict, because both branches are making a contributory change, and those contributions can conflict.

这正是您通过采摘樱桃所做的.Cherry-pick只是无处创建新的提交.好吧,不是无处不在,但重点是,这不是合并-即使您继续调用合并,这不会使其合并.这只是该分支上的一个新的完全独立的提交.因此,您开始了冲突-现在您想知道如何摆脱冲突.

And that is exactly what you did by cherry-picking. Cherry-pick just creates a new commit out of nowhere. Well, not nowhere, but the point is, it is not a merge — even though you keep calling it a merge; that does not make it a merge. It is just a new totally independent commit on this branch. So you started a conflict — and now you want to know how to get out of it.

现在,很明显,您可以通过解决冲突摆脱这种情况并完成合并.但是麻烦是,这并不一定解决未来合并的全部困难.

Now, you can get out of this situation and complete the merge, obviously, by resolving the conflict. But the trouble is, this does not necessarily solve the whole difficulty for future merges.

这样想.我们将如何解决冲突?如果我们 master 中选择贡献,那么首先对 master 进行的独立提交是什么?但是,如果我们 do master 中选择贡献,那么 master 仍然是 对故事做出独立贡献,并且我们仍然在合并后的下一个时又可能再次发生冲突!

Think of it this way. How exactly are we going to resolve the conflict? If we don't choose the contribution from master, then what was the independent commit on master for in the first place? But if we do choose the contribution from master, then master is still making an independent contribution to the story, and we're still likely to get a conflict again the next time we merge!

例如,在解决冲突并将 br 合并到 master 中,然后在 br 上进行进一步提交之后,我们就在这里:

So for example, here we are after resolving the conflict and merging br into master, and then making a further commit on br:

*   5bad46b (HEAD -> master) merged after resolving conflict
|\  
* | a981153 changed it to z!
* |   086cbed merged once again
|\ \  
* \ \   ec0397a merged branch again
|\ \ \  
* \ \ \   f6535d4 merged branch
|\ \ \ \  
| | | | | * 7dc8475 (br) now it is f
| | | | |/  
| | | | * f6a9ed5 now it is e
| | | |/  
| | | * 82abd8a now it is d
| | |/  
| | * 2546392 changed it to c
| |/  
| * c9fcf16 changed a to b
|/  
* a014c37 start

该图中发生的事情是我们独立更改了文件,使其包含"z".在 master (a981153)上,会扭曲拓扑.同时,我们继续研究 br (f6a9ed5),将文件更改为"e".然后,我们尝试合并-并发生了冲突.好的,所以我们解决了冲突(5bad46b):我们选择"z",因为否则,将文件更改为包含"z"的意义何在?首先?

What's happened in that chart is that we independently changed the file to contain "z" on master (a981153), perverting the topology. Meanwhile, we kept on working on br (f6a9ed5), changing the file to "e". We then tried to merge — and got a conflict. Okay, so we resolved the conflict (5bad46b): we chose "z", because otherwise, what was the point of changing the file to contain "z" in the first place?

好的,但是现在我们继续进行 br (7dc8475)的工作,假设我们现在建议再次合并为 master .但是,当我们切换到 master 并尝试将 br 合并到 master 中时,会发生什么?我们将要发生另一场冲突!

Okay, but now we go on working on br (7dc8475) and let's say we now propose to merge into master again. But what's going to happen when we switch to master and try merge br into master? We're going to get another conflict!

为什么?好吧,最后一次会议的重点(分歧),合并基础是f6a9ed5.从那以后,每个分支机构进行了哪些更改?在 br 上,我们将"e"更改为到"f".但是在 master 上,我们将"e"更改为到"z"-因为这就是我们解决冲突的方式!(换句话说,我们在冲突解决方案本身中进行了更改.)因此,如果我们此时尝试合并,那就是冲突.

Why? Well, the point of last meeting (divergence), the merge base, is f6a9ed5. What change was made on each branch since then? On br, we changed "e" to "f". But on master, we changed "e" to "z" — because that's how we resolved the conflict! (In other words, we made that change in the conflict resolution itself.) So that's a conflict if we try to merge at this moment.

因此,看来我们将不断出现合并冲突 !这是一个恶性循环.摆脱周期的唯一方法是,当我们解决冲突时,最终 br 胜利.这意味着我们必须以某种方式撤消我们在a981153中对 master 进行的独立更改.

So it looks like we are going to get merge conflicts forever going forward! It's a vicious cycle. The only way to get out of the cycle is to eventually let br win when we resolve the conflict. And that is going to mean that the independent change we made on master in a981153 is going to have to be undone somehow.

因此,正如我们所说,您可以现在付款,也可以稍后付款,但是您迟早必须撤消由 master 上的独立更改所引起的拓扑结构异常.

So, as we say, you can pay me now or you can pay me later, but sooner or later you must undo the perversion of the topology that was caused by the independent change on master.

问题是,执行此操作的好方法是什么?答案是我们需要更改 master br 分开的点.我们需要移动合并库.

The question is, what's a good way to do that? The answer is that we need to change the point at which master and br diverge. We need to move the merge base.

尤其是,我们需要将合​​并库移到 master 末端,因为那样,当我们将 br 合并到 master ,我们又回到了 master 没有做出任何贡献的情况;如果合并基础是 master 的结尾,则 master 自合并基础以来未做出任何新贡献.因此,从将来的分歧出发, master 不会做出任何独立的贡献,但是 br 将会做出贡献,我们将再次回到正常的拓扑结构!

In particular, we need to move the merge base to the end of master, because that way, when we merge br into master, we are back to the situation where master is making no contribution; if the merge base is the end of master, then master is making no new contribution since the merge base. So from that point of divergence going forward, master will not make any independent contribution, but br will, and we will be back to our normal topology once again!

这就是为什么我们向后合并 –将 master 合并为 br .这样做之后,问题就解决了;我们可以在 br 上继续前进,并最终从 br 合并到 master 中,它将起作用.这是一个演示图表:

And that is why we merge backward — merge master into br. After doing that, the problem is solved; we can move forward on br and eventually merge forward from br into master, and it will work. Here's a chart that demonstrates:

*   3e9b302 (HEAD -> master) Merge branch 'br'
|\  
| *   df3d049 (br) Merge branch 'master' using 'ours' strategy
| |\  
| |/  
|/|   
* |   5bad46b merged after resolving conflict
|\ \  
* | | a981153 changed it to z!
* | |   086cbed merged once again
|\ \ \  
* \ \ \   ec0397a merged branch again
|\ \ \ \  
* \ \ \ \   f6535d4 merged branch
|\ \ \ \ \  
| | | | | * 7dc8475 now it is f
| | | | |/  
| | | | * f6a9ed5 now it is e
| | | |/  
| | | * 82abd8a now it is d
| | |/  
| | * 2546392 changed it to c
| |/  
| * c9fcf16 changed a to b
|/  
* a014c37 start

在该图中,我们在df3d049处向后合并.通过这样做,我们解决了所有有利于 br 的冲突.实际上,我们解决了 everything ,而赞成 br ;我们使用了 ours 策略,该策略的基本含义是:完全忽略传入分支的贡献,只进行完全由当前分支状态组成的合并提交."

In that chart, we merged backward at df3d049. As we did so, we resolved any conflicts in favor of br. In fact, we resolved everything in favor of br; we used the ours strategy, which basically means: "Disregard the contribution of the incoming branch entirely, and just make a merge commit consisting entirely of the state of the current branch."

然后 now ,当我们将 br 向前合并到 master 中时,它可以正常工作.现在进行正向合并的原因是,在那一刻,汇合点(合并基础)为5bad46b-先前的合并提交到 master 中.从那以后发生了什么?好吧,在 master 上,什么都没有发生;合并基础在进行前向合并之前,对 master 的最后一次提交.因此,在 master 上,我们的文件为"z",并且仍然是"z".同时,在 br 上,我们将"z"更改为到"f".因此,当我们向前合并时,"z"表示更改为"f"在 master 上,从现在开始一切都很好.

And now when we merge br forward into master, it works fine. The reason why the forward merge works now is that at that moment the point of meeting (divergence), the merge base, is 5bad46b — the previous merge commit into master. And what's happened since then? Well, on master, nothing has happened; the merge base is the last commit on master before we make our forward merge. So on master, our file was "z" and it is still "z". Meanwhile, on br, we have changed "z" to "f". So when we merge forward, "z" is changed to "f" on master, and all is well from now on.

但是,请注意,"z"表示 is 更改为"f",在 master 上.我们的解决方案放弃了在a981153上创建的贡献.在该提交中,我们将"a"更改为到"z";现在,"z"表示离开了.但这就是我们要使事情重回正轨时必须付出的代价.创建a981153是错误,只能作为一种临时措施使用;现在已经过去了.

Note, however, that "z" is changed to "f" on master. Our solution has thrown away the contribution that was created at a981153. In that commit, we changed "a" to "z"; now that "z" is gone. But that is the price we have to pay if we're going to get things back on track. Creating a981153 was wrong, and could only operate as a temporary measure; now its time is over.

这篇关于手动合并后如何规范来自合并请求的合并的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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