Git:压缩合并后,反向合并 [英] Git: Merging in reverse direction after squashed merge

查看:365
本文介绍了Git:压缩合并后,反向合并的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的团队正在使用类似Gitflow的工作流程,但是最近一次从developmaster的发行版合并是作为壁球合并无意进行的.当时,我们没有发出任何警报,并认为下次可以正确使用它,但是随后我们不得不对该版本进行修补.现在,我们需要使该修补程序重新合并到develop中,此后又与master分叉了.我们遇到了一些冲突,这是合法的,但是其中大多数是由于git认为master上的squash-merge提交代表其自己的更改提交而不是与develop合并而引起的.

My team is using a Gitflow-like workflow, but a recent merge from develop to master for a release was unintentionally done as a squash merge. At the time, we didn't raise any alarms and figured we'd get it right next time, but then we had to do a hotfix off of that release. Now, we need to get that hotfix merged back into develop, which has since diverged from master. We're getting conflicts, some legitimate, but most of them noise due to git thinking that the squash-merge commit on master represents its own separate commit of the changes, rather than a merge from develop.

图表可能有助于说明问题:

A graph may help illustrate the issue:

 A ---------- D -- G (master)
  \
   \- B -- C -- E -- F (develop)

在这种情况下,D是B和C的壁球合并的结果(而不是常规合并的常规合并).请注意,git diff C D返回空-即它们的内容相同.

In this case, D is the result of a squash-merge of B and C (instead of a regular merge, as we would have normally done). Note that git diff C D returns empty - i.e. they are identical in content.

现在,我想将master合并到develop中;由于EFG之间的合法重叠,我预计会有一些冲突(因此,我不能简单地全局地说使用我们的"或使用他们的").但是我基本上在BCD中的所有内容上都有冲突,大概是因为git将D(可以理解)视为其自己的提交,而在master的单独提交链中,从A开始

Now, I want to merge master into develop; I expect some conflicts due to legitimate overlap between E, F, and G (hence I can't simply globally say "use ours" or "use theirs"). But I'm getting conflicts for basically everything in B, C, and D, presumably because git views D (understandably) as its own commit in a separate chain of commits on master starting from A.

长话短说,我希望获得的是类似于相对于这两个相同提交(CD)的合并"而不是相对于A的合并".有点像rebase --onto,但我想是为了合并.

Long story short, what I'm hoping for is something like "merge relative to these two identical commits (C and D)" rather than "merge relative to A". Sort of like rebase --onto, but for merging, I guess.

FWIW,我知道我可以手工解决冲突.我只是很好奇,是否有一种方法可以跳过通过创建D时执行的壁合并而不是常规合并而引入的所有垃圾冲突.

FWIW, I know that I can just resolve the conflicts by hand; I'm just curious if there's a way to skip all the garbage conflicts introduced by having done a squash-merge instead of a regular merge when D was created.

推荐答案

更新-我忘记了有关其工作原理的重要信息;固定.

UPDATE - I had forgotten important information about exactly how this works; fixed.

现在,我假设进行历史记录重写(以及随后的清理)并不是一个切实可行的解决方案...

For now I'll assume that doing a history rewrite (and the subsequent clean-up) isn't really a practical solution...

在这种情况下,最简单的方法是在合并过程中使用git replace.如果CD具有相同的内容,这将不起作用.

In this specific case, the simplest hack would be to use git replace during the merge. This would not work if not for the fact that C and D have the same content.

在克隆中你可以说

git replace --graft <E> <D>

(其中<E><D>是解析为相应提交的表达式;在上面的示例中,它可能是git replace --graft develop^ master^).这将创建一个新的提交E',其外观类似于E,但其父级为D.然后,它使用E'代替E-因此,当操作将git引导至E时,它仍然会看到E的提交ID,但会从E'获取有关该提交的其余信息. .身体上你有

(where <E> and <D> are expressions that resolve to the corresponding commits; in the above example, this might be git replace --graft develop^ master^). This creates a new commit E' that "looks like" E, but its parent is D. It then uses E' as a replacement for E - so when an operation leads git to E, it still sees Es commit ID, but it gets the rest of its info about that commit from E'. Physically you have

                E'
               /
 A ---------- D -- G (master)
  \
   \- B -- C -- E (REPLACE:E')
                 \
                  F (develop)

那你呢

git chekcout develop
git merge master

(或者也许是git merge hotfix-branch,但是您没有在图形中显示它,因此我们将使用简化的示例)...现在,merge命令可以看到"

(or maybe git merge hotfix-branch but you didn't show that in your graph, so we'll go with the simplified example)... Now the merge command "sees"

A ---------- D -- G (master)
              \
               (E|E') -- F (develop)

,因此它使用D作为合并基础.因为CD具有相同的内容,所以计算出的合并结果应为应有的结果.结果看起来像"

so it uses D as the merge base. Because C and D have the same content, the calculated merge result is what it should be. The result "looks like"

A ---------- D ------------ G (master)
              \              \
               (E|E') -- F -- M (develop)

这是真的

                E'
               /
 A ---------- D ------ G (master)
  \                     \
   \                F -- M (develop)
    \              /
     \- B -- C -- E (REPLACE:E')

现在,D .. M周围的历史记录看起来很有趣",这就是这样做的缺点(而不是用真实的合并替换D的历史记录校正). M是边界邪恶合并",但是由于默认合并仍然会发生冲突(并且由于计算结果是冲突的自然"解决方案),因此并不可怕.

Now the history around D..M "looks funny", and that's the down side of doing this (rather than a history correction to replace D with a true merge). M is a borderline "evil merge", but since the default merge would conflict anyway (and since the calculated result is the "natural" resolution of the conflict) it's not terrible.

完成此操作后,您将不再需要更换.将来masterdevelop之间的合并将仍然将G作为合并基础,因此之前的混乱并不重要.

Once this is done you no longer need the replacement. Future merges between master and develop will see G as the merge base anyway, so the messiness that precedes it doesn't matter.

这篇关于Git:压缩合并后,反向合并的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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