我正在尝试将两个分支组合成一个新的空分支,每个分支具有不同的根提交。这不是通常的合并,因为我不想只在最后一次提交中合并分支(在这种情况下,新分支将有一个合并提交,并且"下面"仍然是两个单独的历史记录。新分支仍将有两个根提交。
在我的场景中,一个重要的事实是这两个分支完全不相关。任何一个分支的提交都不会影响其他分支提交的路径 => 不会有冲突。
让我们假设以下分支:
A---B-----C-D
X---Y-Z
这就是我正在寻找的:
A-X-B-Y-Z-C-D
重点是我想按时间顺序提交。如何实现?
你写道:
在我的场景中,一个重要的事实是这两个分支完全不相关。任何一个分支的提交都不会影响其他分支提交的补丁 => 不会有冲突。
当然,如果您预计会出现许多冲突,那么您建议的"拼接"操作可能是一个坏主意。让我们假设,确实不会发生任何坏事。
如果在开始时,您的存储库如下所示
A---B------C--D [branch1]
X---Y--Z [branch2]
您可以按照下面概述的过程自动将两个分支的提交"拼接"到单个分支中,同时保持时间顺序。
"拼接"两个不相关的分支
确保您处于干净的工作状态;然后签出
branch1
并将branch2
合并到其中:git checkout branch1 git merge branch2
这将产生
A---B------C--D---E [HEAD=branch1] / X---Y--Z------- [branch2]
现在,我知道这不是你想要的,但请耐心等待我一秒钟。我们将使用合并提交
E
来立即访问"双方的祖先"。签出
branch2
并将其重置为提交A
。git checkout branch2 git reset --hard A
您将处于以下情况:
A [HEAD=branch2] ---B------C--D---E [branch1] / X---Y--Z-------
生成一个列表(按时间顺序(,列出可从
branch1
访问但不能从branch2
访问的所有非合并提交:git rev-list --no-merges --reverse branch2..branch1
这应该产生以下提交列表:
X
、B
、Y
、Z
、C
、D
;在步骤 1 中创建的提交E
将不会在该列表中,因为我们使用了--no-merges
标志。
在 branch2
(A( 之上挑选这些提交。git cherry-pick `git rev-list --no-merges --reverse branch2..branch1`
然后,您的存储库将如下所示:
A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2] ---B-----C-D---E [branch1] / X---Y-Z------
删除
branch1
:git branch -D branch1
编辑:正如您正确指出的,由于
branch1
没有完全合并到当前分支(branch2
(,因此仅使用-d
在这里是行不通的;您需要改用-D
标志。然后,您的回购将简单地
A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2]
(可选(重命名
branch2
:git branch -m branch2 <more_meaningful_name>
泛化到两个以上的分支
假设你有 n 个完全不相关的分支:branch1
、branch2
、...、branchn
,其中 branch1
对应于根提交是整个仓库中最早提交的分支;让我们称该提交为A
。
A ----- o ---- o [branch1]
o ----- o ---- o -- o [branch2]
...
o ----- o - o [branchn]
如果您不知道哪个提交A
,您可以通过运行来识别它
git rev-list --reverse --max-parents=0 --all
A
的提交 ID 将是该命令输出中列出的第一个。您可以通过运行以下命令来识别branch1
哪个分支:
git branch -r --contains `git rev-list --reverse --max-parents=0 --all | head -1`
然后,两个分支案例中的程序概述变为:
通过将除
branch1
以外的所有分支合并到branch1
中,创建一个可以访问所有分支祖先的提交。(与双分支案例相同(
- (与双分支案例相同(
- (与双分支案例相同(
- 删除除
branch2
以外的所有分支。 - (与双分支案例相同(
快速简单的合并解决方案是,
假设 A---B-----C-D(是分支 1(和 X---Y-Z(是分支 2(。从分支 2 (git format-patch -n( 获取所有补丁,然后将所有补丁应用到分支 1 (git am *.patch( 之上,然后在您希望序列使用 git rebase -i HEAD~n 的位置进行洗牌
希望对您有所帮助!