我如何“拼接”?两个(或更多)完全不相关的线性分支血统变成新的? [英] How can I "splice" two (or more) completely unrelated linear branch ancestries into a new one?

查看:93
本文介绍了我如何“拼接”?两个(或更多)完全不相关的线性分支血统变成新的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将两个不同的根提交分支合并成一个新的空分支。这不是通常的合并事情,因为我不想让分支只在最后一次提交时合并(在这种情况下,新分支会有合并提交,而下方仍然有两个独立的历史记录。 )。

在我的场景中,一个重要的事实是两个分支完全不相关。

让我们假设以下分支:

  A --- B ----- CD 
X --- YZ

这就是我要找的:

  AXBYZCD 

主要观点是我想按时间顺序进行提交。
如何实现?

解决方案

您写:


我的情况中的一个重要事实是,两个分支完全不相关。任何一个分支的提交都不会影响其他分支的补丁'commitits =>不会有冲突。

当然,拼接如果您预计会出现许多冲突,您提出的操作可能是一个糟糕的主意。让我们假设,没有什么不好的事情会发生。



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

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

X --- Y - Z [branch2]

您可以按照下面列出的步骤自动将两个分支的提交拼接为一个分支,按时间顺序排列。

拼接两个不相关的分支




  1. 制作确定你处于干净的工作状态;然后检查 branch1 并将 branch2 合并到它中:

      git checkout branch1 
    git merge branch2

    将产生

      A --- B ------ C  -  D --- E [HEAD = branch1] 
    /
    X --- Y - Z ------- [branch2]

    现在,我知道那不是你想要的,而是忍受我一秒钟。我们将使用合并提交 E 来一次访问双方血统。

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

      git checkout branch2 
    git reset --hard A

    您会遇到以下情况:

      A [HEAD =分支2] 
    \
    --- B ------ C - D --- E [branch1]
    /
    X --- Y - Z ------- $ b $从<$ c $生成所有可到达的非合并提交列表(按时间顺序排列)b


  3. c> branch1 但不是从 branch2

      git rev-list --no-merges --reverse branch2..branch1 

    以下是提交列表: X B Y Z C D ;在步骤1中创建的提交 E 不在该列表中,因为我们使用了 - 不合并 flag。


  4. branch2 (A)之上挑选那些提交。 >

      git cherry-pick`git rev-list --no-merges --reverse branch2..branch1` 

    您的回购将如下所示:

      A  -  X' -  B' -  Y' -  Z' -  C' -  D'[HEAD = branch2] 
    \
    --- B-- --- CD --- E [branch1]
    /
    X --- YZ ------


  5. 删除 branch1

      git分支-D branch1 

    修改:正如您正确指出的,因为 branch1 没有完全合并到当前分支( branch2 )中,只需使用 - d 不会在这里;您需要使用 -D 标志。



    您的回购将简单地为

      A  -  X' -  B' -  Y' -  Z' -  C' -  D'[HEAD = branch2] 


  6. (可选)重命名 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 

<$ c $的提交ID c> A 将会在该命令的输出中首先列出。你可以通过运行来识别哪个分支是 branch1

  git分支-r --contains`git rev-list --reverse --max-parents = 0 --all |头部-1` 

然后程序在两分支情况下的轮廓变为:


  1. 通过合并除 branch1 转换为 branch1


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


  3. (与两分支案例相同)

  4. (与两分支案例相同)

  5. 删除除 branch2 之外的所有分支。

  6. (与两分支大小写相同)


I'm trying to combine two branches each with different root commit into a new, empty branch. This is not the usual merge thing as i don't want to have the branches combined only in the last commit (in that case, the new branch would have a merge commit and 'below' still two seperate histories. The new branch would still have two root commits.).

One important fact in my scenario is that both branches are completely unrelated. None commit of either branch affects pathes of the other branches' commits => There will be no conflicts.

Let's assume the following branches:

A---B-----C-D
  X---Y-Z

This is what i am looking for:

A-X-B-Y-Z-C-D

The main point is that i want to have the commits in chronological order. How to achieve?

解决方案

You write:

One important fact in my scenario is that both branches are completely unrelated. No commit of either branch affects patches of the other branches' commits => There will be no conflicts.

Of course, the "splicing" operation you suggest is probably a bad idea if you anticipate that many conflicts will arise. Let's assume that, indeed, nothing bad will happen.

If, at the beginning, your repo looks like this

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

  X---Y--Z [branch2]

you can follow the procedure outlined below to automatically "splice" commits from both branches into a single branch, while maintaining chronological order.

"Splicing" two unrelated branches

  1. Make sure you're in a clean working state; then check out branch1 and merge branch2 into it:

    git checkout branch1
    git merge branch2
    

    That will yield

    A---B------C--D---E [HEAD=branch1]
                     /
      X---Y--Z------- [branch2]
    

    Now, I know that's not what you want, but bear with me for a second. We will use merge commit E to have access to "the ancestry on both sides" at once.

  2. Check out branch2 and reset it to commit A.

    git checkout branch2
    git reset --hard A
    

    You'll be in the following situation:

    A [HEAD=branch2]
     \
      ---B------C--D---E [branch1]
                      /
       X---Y--Z------- 
    

  3. Generate a list (in chronological order) of all the non-merge commits reachable from branch1 but not from branch2:

    git rev-list --no-merges --reverse branch2..branch1
    

    This should yield the following list of commits: X, B, Y, Z, C, D; commit E, which was created in Step 1 will not be in that list, because we used the --no-merges flag.

  4. Cherry-pick those commits on top of branch2 (A).

    git cherry-pick `git rev-list --no-merges --reverse branch2..branch1`
    

    Your repo will then look as follows:

    A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2]
     \
      ---B-----C-D---E [branch1]
                    /
       X---Y-Z------ 
    

  5. Delete branch1:

    git branch -D branch1
    

    Edit: As you correctly remarked, because branch1 is not fully merged into the current branch (branch2), using just -d won't do, here; you need to use the -D flag instead.

    Your repo will then simply be

    A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2]
    

  6. (Optionally) Rename branch2:

    git branch -m branch2 <more_meaningful_name>
    

Generalization to more than two branches

Let's assume you have n completely unrelated branches: branch1, branch2, ..., branchn, where branch1 corresponds to the branch whose root commit is the oldest commit in the entire repository; Let's call that commit A.

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

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

...

 o ----- o - o [branchn]

If you don't know which commit is A, you can identify it by running

git rev-list --reverse --max-parents=0 --all

The commit ID of A will be the first listed in the output of that command. And you can identify which branch is branch1 by running:

git branch -r --contains `git rev-list --reverse --max-parents=0 --all | head -1`

Then the procedure outlines in the two-branch case becomes:

  1. Create a commit that has access to the ancestry of all branches, by merging all branches other than branch1 into branch1.

  2. (same as in two-branch case)

  3. (same as in two-branch case)
  4. (same as in two-branch case)
  5. Delete all branches other than branch2.
  6. (same as in two-branch case)

这篇关于我如何“拼接”?两个(或更多)完全不相关的线性分支血统变成新的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆