使用git合并两个非常不同的分支?

13
我有一个master主分支和一个verydifferentbranch,它们最初的祖先相同,大约在300次提交之前。现在verydifferentbranch已经完成了所有功能,我想将其放到主branch下面。尝试进行rebase会导致每个补丁都有很多合并冲突,以至于要处理所有冲突将成为一个庞大的项目。
我不知道该怎么办,除了强制将verydifferentbranch的头部推送到master分支。但这样做会丢失所有历史记录,这不是我真正想要的。
还有其他选项吗?

2
为什么不考虑合并? - Michaël Witrant
一个不幸的“你应该”非回答:从master分支频繁合并到verydifferentbranch分支至少可以分散痛苦,假设verydifferentbranch分支与master分支保持兼容。 (如果没有,那么问题就出现了,为什么它们在整个开发过程中不兼容,但现在应该兼容了。) - jtniehof
4个回答

20

听起来你的历史记录是这样的:

...---o---A---o---...---o---o---B   master
           \
            o---o---...---o---C     verydifferentbranch

您说您担心如果强制推送verydifferentbranchmaster,将会丢失历史记录。这样的操作相当于扔掉了从AB之后的所有内容。

您可以通过合并它来保留历史记录,或者只需在被弃用的分支末尾放置一个标签并将其保留未合并即可。

使用合并

合并将允许您保留历史记录的两个方面:

...---o---A---o---...---o---o---B
           \                     \
            o---o---...---o---C---M  master

你所做的合并类型将决定为提交M创建的内容。在你的情况下,普通合并(使用recursive合并策略)似乎会产生大量冲突。如果你确实需要合并A..B提交中的更改,那么除了通过合并或变基解决所提出的冲突外,别无选择。(如果您能够更频繁地合并或变基以处理冲突,则在将来可能会遇到更少的问题。)但是,如果您只想让M具有与C相同的内容(即您想忽略由A..B提交表示的更改),则可以使用ours合并策略。 git-merge(1)描述了ours合并策略:

这解决了任意数量的头,但合并的结果树始终是当前分支头的树,有效地忽略了所有其他分支的更改。它旨在用于取代旁路的旧开发历史记录。请注意,这与递归合并策略的-Xours选项不同。

您可以像这样生成消息为Merge commit 'abandoned/foo-features'的M:
git tag -m 'describe reason for abandonment here...' \
    abandoned/foo-features master                   # tag abandoned branch tip
git checkout verydifferentbranch                    # checkout dominant branch
git branch -M verydifferentbranch master            # replace master
git merge -s ours abandoned/foo-features            # merge only other's history
git tag -d abandoned/foo-features                   # optional: delete the tag
git push wherever master tag abandoned/foo-features # publish them

这些命令的变化将为您提供略有不同的自动提交消息,适用于M(您始终可以使用git merge -m提供自己的消息,或者在之后使用git commit --amend进行修改)。
主要问题是,生成的master将具有两个历史记录片段,但没有来自原始master侧的任何更改(这些更改仍然存在于历史记录中,只是它们未在由提交M引用的树中表示)。

悬而未决

如果“重写”master是可接受的(即不存在基于任何提交A..B的其他工作,或者涉及的用户不介意从重写中恢复所需的工作),则可以在当前master的末端留下一个标签,并将master替换为verydifferentbranch
...---o---A---o---...---o---o---B   (tag: abandoned/foo-features)
           \
            o---o---...---o---C      master

像这样安排:

git tag -m 'describe reason for abandonment here...' \
    abandoned/foo-features master                    # tag abandoned branch tip
git branch -M verydifferentbranch master             # replace master
git push wherever +master tag abandoned/foo-features # publish them

5
这就是为什么存在 git merge 功能的原因。
$> git checkout master
$> git merge verydifferentbranch

如果你第一次尝试合并代码时发现有很多冲突(如果它们已经如你所说的那样分歧很大),这是很正常的。但是,如果你能保持对事情的掌控,在初始合并之后就不会太糟糕。


1

你为什么要先进行一次变基呢?这很可能会导致你的变更集出现问题,因为你的变更集将会从你与主分支分离的提交开始寻找文件版本。

使用 git 合并代替。


0

我发现通过将verydifferentbranch上的每10个提交合并到master中,并通过这种方式解决冲突,更容易理解和解决合并冲突。是的,如果你有300个提交,这意味着你需要进行30次合并,但是每次合并的分歧远比一次性尝试合并它们要少得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接