[英]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
中引入,而其他提交包含它,因此很容易制定说明,当给定REMOTE
、 LOCAL
和BASE
的片段时如何解决冲突:
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?是否有一些工具可以将此类指令传递给?
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
。
Looks promising but merge conflict resolution seems not yet implemented and the project is in maintenance mode.看起来很有希望,但合并冲突解决似乎尚未实施,并且该项目处于维护模式。
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:我真的在寻找一种以编程方式解决这个问题的方法,但是由于有很多关于如何手动完成的建议,我不妨在这里收集它们:
mybranch
在mybranch
顶部应用替换Would work if i was the owner, but I am not.如果我是所有者会工作,但我不是。 replace
is on origin/master
and won't come off. replace
位于origin/master
上,不会关闭。
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
中。
There are too many merge conflicts to resolve them manually, even with the help of an IDE.即使在 IDE 的帮助下,也有太多的合并冲突无法手动解决。
mybranch
into master只需将mybranch
合并到 masterEasier 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
中发生的foo
到bar
的机械替换确实需要应用于提交*
然后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 的替换,但在复制B
和C
时完成不同的替换——来自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.