简体   繁体   English

如何以编程方式解决合并冲突?

[英]How can I programmatically resolve merge conflicts?

I have a branch mybranch with all sorts of changes and need to rebase it on master .我有一个带有各种更改的分支mybranch ,需要在master上重新设置它。 The difference between the current and the target base of mybranch is one commit replace that consists entirely of replacing (most but not all) occurrences of foo with bar . mybranch的当前基础和目标基础之间的区别是一个提交replace ,它完全包括用bar替换(大多数但不是全部)出现的foo This operation can be repeated with reasonable effort at any revision.可以在任何修订中以合理的努力重复此操作。

* 46de000 (mybranch) my latest change
* ...
* 452e6f5 my second change
* 452e6f4 my first change
| * dc5024d (origin/master, master, tag: replace) replace /foo/bar/
|/  
* 5fab176 common base
* 7bbe99e initial commit

The commits in mybranch do not change any occurrence of foo itself but they do change several lines that contain foo . mybranch中的提交不会更改foo本身的任何出现,但它们确实更改了包含foo的几行。 So when I rebase mybranch on replace I need to resolve many merge conflicts, more than are feasible to resolve by hand.所以当我 rebase mybranch on replace我需要解决许多合并冲突,而不是手动解决。 Those conflicts cannot be automatically resolved because replace changes a line one way and the commits of mybranch change it another way.这些冲突无法自动解决,因为replace以一种方式更改了一行,而mybranch的提交以另一种方式更改了它。 But since the word bar is only introduced in replace and other commit contains it it is easy to formulate instructions for how to resolve a conflict when given snippets for REMOTE , LOCAL and BASE :但是由于bar一词仅在replace中引入,而其他提交包含它,因此很容易制定说明,当给定REMOTELOCALBASE的片段时如何解决冲突:

if base.contains('foo') and local.contains('bar'):
   return remote.replace('foo', 'bar')
else:
   exit('unexpected conflict: $remote $local $base')

Is there some tool that I can pass such instructions to?是否有一些工具可以将此类指令传递给?

Attempts at a solution尝试解决方案

programmatically以编程方式

git-filter-repo can batch rewrite history git-filter-repo可以批量改写历史

I don't think there is a way to modify mybranch in a way that avoids merge conflicts.我认为没有办法以避免合并冲突的方式修改mybranch

gitPython gitPython

Looks promising but merge conflict resolution seems not yet implemented and the project is in maintenance mode.看起来很有希望,但合并冲突解决似乎尚未实施,并且该项目处于维护模式。

manually after all毕竟手动

I'm really looking for a way to solve this programmatically, but as there have been many suggestions on how to do it manually I might as well collect them here:我真的在寻找一种以编程方式解决这个问题的方法,但是由于有很多关于如何手动完成的建议,我不妨在这里收集它们:

Apply the replacement on top of mybranchmybranch顶部应用替换

Would work if i was the owner, but I am not.如果我是所有者会工作,但我不是。 replace is on origin/master and won't come off. replace位于origin/master上,不会关闭。

Apply the replacement on top of mybranch , squash it, rebase on master.mybranch顶部应用替换,压扁它,在 master 上重新设置。

After applying the replace operation on top of mybranch as a new commit replace_on_top and squashing everything into one commit this single commit can be rebased on master with git rebase -Xtheirs master .mybranch顶部应用替换操作作为新提交replace_on_top并将所有内容压缩到一个提交中之后,可以使用git rebase -Xtheirs master master Downside is that I lose the separation of mybranch into several commits.缺点是我失去了将mybranch分成几个提交的分离。 Maybe this replace_on_top can somehow be automatically distributed to the first commits in mybranch that change a file?也许这个replace_on_top可以以某种方式自动分发到mybranch中更改文件的第一个提交? Then I could keep the separate commits in mybranch .然后我可以将单独的提交保存在mybranch中。

With GUI or IDE带 GUI 或 IDE

There are too many merge conflicts to resolve them manually, even with the help of an IDE.即使在 IDE 的帮助下,也有太多的合并冲突无法手动解决。

Just merge mybranch into master只需将mybranch合并到 master

Easier than a rebase because all conflicts come at once, but I really want to rebase.比 rebase 更容易,因为所有冲突都会同时出现,但我真的很想 rebase。

There is no existing Git tool for this.没有用于此目的的现有 Git 工具。 (There was a proposal recently on the Git mailing list for one, but I believe the problem itself is a little under-specified to start with and the result is that no one is entirely sure how to proceed.) (最近在 Git 邮件列表上有一个提案,但我认为问题本身在开始时有点未指定,结果是没有人完全确定如何进行。)

Fundamentally, what you'd like to do is:从根本上说,你想做的是:

  • Take each commit to be copied (as in what git rebase does with a copy) and make two temporary commits—one of it, and one of its parent—with the mechanical substitution in place.获取要复制的每个提交(如git rebase对副本所做的那样)并进行两次临时提交——一个是它,一个是它的父节点——并且机械替换到位。

    Note that the "replacement" temporary parent commit is just the commit we copied last time, if we've already copied one commit.请注意,如果我们已经复制了一个提交,那么“替换”临时父提交只是我们上次复制的提交。 This can be used for optimization but is not relevant to the overall process.这可用于优化,但与整个过程无关。 But there is one caveat;但是有一个警告; see below.见下文。

  • Using the copied child that has the copied parent, do the git cherry-pick operation that rebase will do.使用具有复制父级的复制子级,执行变基将执行的git cherry-pick操作。 Since both parent and child have the mechanical substitution already done, only the remaining changes show up in the diff from parent to HEAD , and in the diff from parent to child.由于父母和孩子都已经完成了机械替换,因此只有剩余的更改显示在从父母到HEAD的差异中,以及从父母到孩子的差异中。

    If there are conflicts, present and resolve them in the usual way.如果存在冲突,请以通常的方式呈现并解决它们。

  • Repeat until all commits are copied, in the usual way, then move the one branch name as git rebase usually does.以通常的方式重复直到所有提交都被复制,然后像git rebase通常那样移动一个分支名称。

The caveat is that in this "make temporary commits" process, we may want that mechanical substitution process depend on the depth within the branch .需要注意的是,在这个“临时提交”过程中,我们可能希望机械替换过程取决于分支内的深度 Consider:考虑:

          A--B--C   <-- topic (to be rebased)
         /
...--o--*--o--F--o--...--@   <-- main

We want to copy the effect of A , B , C to commit @ .我们要将A , B , C效果复制到 commit @ But there was a "flag day" commit: here it's commit F .但是有一个“国旗日”提交:这里是提交F Here, some sort of mechanical substitution was done.在这里,进行了某种机械替代。

In this particular rebase sequence, it's clear that the mechanical replacement of foo to bar that happened in F does need to be applied to commits * and then A - B - C .这个特定的变基序列中,很明显F中发生的foobar的机械替换确实需要应用于提交*然后A - B - C But what if we have a more complex structure:但是如果我们有一个更复杂的结构怎么办:

...--o--*--F---o--G--o--...--@   <-- main
         \      \
          A------M---B--C   <-- topic (to be rebased)

Here we'd like to copy ABC as before, but there were two flag days.在这里,我们想像以前一样复制ABC ,但是有两个标志日。 We want the foo-to-bar substitution done when copying A , but a different substitution—the one from G —done when copying B and C .我们希望在复制A时完成 foo 到 bar 的替换,但在复制BC时完成不同的替换——来自G的替换。 (And in the most general case, if M dropped the flag-day stuff from F because o was the important part, we want both done.) (在最一般的情况下,如果M因为o是重要部分而从F中删除了国旗日的东西,我们希望两者都完成。)

If we ignore the complication case, in which some flag days are merged in at some point and others aren't, we get a pretty straightforward set of operations that git rebase could do if it were programmed for it.如果我们忽略复杂情况,其中一些标志日在某些时候合并,而另一些则没有,我们会得到一组非常简单的操作,如果git rebase可以为它编程,它可以执行。 But it isn't.但事实并非如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何解决拉取请求中的复杂合并冲突? - How can I resolve complex merge conflicts in my pull request? 如何通过保留我更改的文件版本来解决 git 合并冲突? - How can I resolve git merge conflicts by keeping my version of files that I changed? 如何解决 monorepo 中的合并冲突? - How to resolve merge conflicts in a monorepo? 如何解决 Git 存储库中的合并冲突? - How do I resolve merge conflicts in a Git repository? 在Git中,如果我将分支B合并到A中并解决合并冲突,那么当再次将A合并到B中时是否仍会发生合并冲突? - In Git, if I merge branch B into A and resolve merge conflicts, can merge conflicts still arise when merging A into B again? 如何解决EGit中多个提交中的合并冲突? - How to resolve merge conflicts in multiple commits in EGit? 我们如何在没有图形化差异/合并工具的系统上手动解决git补丁合并冲突 - How can we resolve git patch merge conflicts manually on a system where no graphical diff/merge tool is available 自动解决合并冲突 - Automatically resolve merge conflicts 如何解决 Git 分支之间的文件命名冲突? - How can I resolve file naming conflicts between Git branches? 如何以编程方式查找 Git 冲突周围的行号? - How can I programmatically find the line numbers around Git conflicts?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM