如何将两个(或更多)完全不相关的线性分支祖先"拼接"成一个新的?

Hen*_*ing 3 git merge branch

我正在尝试将每个具有不同根提交的两个分支组合成一个新的空分支.这不是通常的合并事情,因为我不希望仅在最后一次提交中将分支组合在一起(在这种情况下,新分支将具有合并提交,并且"下方"仍然是两个单独的历史.新分支仍将是有两个root提交.)

我的场景中的一个重要事实是两个分支完全不相关.任何一个分支的提交都不影响其他分支的提交的路径=>不存在冲突.

我们假设以下分支:

A---B-----C-D
  X---Y-Z
Run Code Online (Sandbox Code Playgroud)

这就是我要找的:

A-X-B-Y-Z-C-D
Run Code Online (Sandbox Code Playgroud)

重点是我希望按时间顺序进行提交.怎么实现?

jub*_*0bs 5

你写:

我的场景中的一个重要事实是两个分支完全不相关.任何一个分支的提交都不会影响其他分支的提交补丁=>不存在冲突.

当然,如果您预计会出现许多冲突,那么您所建议的"拼接"操作可能是一个坏主意.我们假设确实没有什么不好的事情会发生.

如果,在开始时,您的回购看起来像这样

A---B------C--D [branch1]

  X---Y--Z [branch2]
Run Code Online (Sandbox Code Playgroud)

您可以按照下面列出的步骤自动将两个分支的提交"拼接"到一个分支中,同时保持按时间顺序排列.

"拼接"两个不相关的分支

  1. 确保你处于干净的工作状态; 然后签出branch1并合并branch2到它:

    git checkout branch1
    git merge branch2
    
    Run Code Online (Sandbox Code Playgroud)

    那会产生

    A---B------C--D---E [HEAD=branch1]
                     /
      X---Y--Z------- [branch2]
    
    Run Code Online (Sandbox Code Playgroud)

    现在,我知道那不是你想要的,而是忍受我一秒钟.我们将使用合并提交E立即访问"双方的祖先".

  2. 签出branch2并重置它以提交A.

    git checkout branch2
    git reset --hard A
    
    Run Code Online (Sandbox Code Playgroud)

    您会遇到以下情况:

    A [HEAD=branch2]
     \
      ---B------C--D---E [branch1]
                      /
       X---Y--Z------- 
    
    Run Code Online (Sandbox Code Playgroud)
  3. 生成一个列表(按时间顺序),可以从以下位置访问branch1但不能从branch2以下位置访问:

    git rev-list --no-merges --reverse branch2..branch1
    
    Run Code Online (Sandbox Code Playgroud)

    这应该产生的提交以下列表:X,B,Y,Z,C,D,E在步骤1中创建的commit 将不在该列表中,因为我们使用了该--no-merges标志.

  4. 樱桃 - 在branch2(A)之上挑选那些提交.

    git cherry-pick `git rev-list --no-merges --reverse branch2..branch1`
    
    Run Code Online (Sandbox Code Playgroud)

    您的回购将如下所示:

    A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2]
     \
      ---B-----C-D---E [branch1]
                    /
       X---Y-Z------ 
    
    Run Code Online (Sandbox Code Playgroud)
  5. 删除branch1:

    git branch -D branch1
    
    Run Code Online (Sandbox Code Playgroud)

    编辑:正如你正确评论的那样,因为branch1没有完全合并到当前的branch(branch2)中,-d所以在这里使用就行了; 你需要使用-D标志.

    那么你的回购将会是

    A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2]
    
    Run Code Online (Sandbox Code Playgroud)
  6. (可选)重命名branch2:

    git branch -m branch2 <more_meaningful_name>
    
    Run Code Online (Sandbox Code Playgroud)

推广到两个以上的分支机构

假设您有n个完全不相关的分支:branch1,, branch2... ,, branchn其中branch1对应于其根提交是整个存储库中最早提交的分支; 我们称之为提交A.

A ----- o ---- o [branch1]

   o ----- o ---- o -- o [branch2]

...

 o ----- o - o [branchn]
Run Code Online (Sandbox Code Playgroud)

如果您不知道哪个提交A,则可以通过运行来识别它

git rev-list --reverse --max-parents=0 --all
Run Code Online (Sandbox Code Playgroud)

提交ID A将是该命令输出中列出的第一个提交ID .您可以branch1通过运行来识别哪个分支:

git branch -r --contains `git rev-list --reverse --max-parents=0 --all | head -1`
Run Code Online (Sandbox Code Playgroud)

然后,在两个分支的情况下的程序概述变为:

  1. 通过合并除branch1into 之外的所有分支,创建可以访问所有分支的祖先的提交branch1.

  2. (与双分支案例相同)

  3. (与双分支案例相同)
  4. (与双分支案例相同)
  5. 删除除以外的所有分支branch2.
  6. (与双分支案例相同)