如何在GIT中将分支合并到另一个分支?

Pri*_*lia 6 git branch

让我详细解释一下这个问题.

我有一个主git分支,我在其上创建了一个新的side branch bug10101010,现在我不想将bug10101010合并到main.到目前为止一切都很好.现在我有一个相同产品的不同分支,名为legacy.我不想将bug10101010合并到GIT中的遗留分支.

有任何想法吗?

我不能直接合并它,因为分支bug10101010是从主分支中分离的,而在遗产中我只需要分支bug10101010与其父分支之间的差异.

Von*_*onC 6

你应该git rebase --onto在这里使用,并指定一个范围.
(见git rebase手册页:

将基于一个分支的主题分支移植到另一个分支,假装您使用分支来自后一个分支的主题分支rebase --onto.

).

当然,这会将您的bug10分支移动到分支的顶部legacy,这不是您想要/需要的.

所以,一个解决方法是做一个克隆的回购是重订,然后合并是"增强" legacy分支(一个在克隆回购,与bug10在它上面的修改),以本地和当前legacy分支(你想要的一个修改,而bug10单独留下).

现在:

  • 这涉及额外的回购(可能导致磁盘空间限制)
  • 总而言之,这相当于定义一个补丁并将其应用于legacy分支,因此其他答案(补丁)是有效的(并且更简单).
  • 我在此方法中看到的唯一的好处是定义在你衍合你想要的东西(像旧有环境的机会bug10提交),推只有分支之前legacy你原来的回购(你会不会推bug10,因为它的历史本来完全改写!)

我只想看看它是否有效,所以......让我们测试一下这种方法.
(Git1.6.5.1,在旧的XP SP2上,由于该Start-Transcript命令而带有Powershell 1.0会话)


PS D:\> mkdir git
PS D:\> cd git
PS D:\git> mkdir tests
PS D:\git> cd tests
PS D:\git\tests> git init mainRepo
Run Code Online (Sandbox Code Playgroud)

我喜欢我不再拥有git repo目录,然后输入它git init!从1.6.5开始:

" git init" 在给出额外参数(即" ")时学习到mkdir/ chdir进入目录git init this.

这很棒!

让我们创建3个文件,用于3种不同的目的.
(为了示例,我将保持每个分支的文件修改:在合并或rebase期间没有冲突.)

PS D:\git\tests> cd mainRepo
PS D:\git\tests\mainRepo> echo mainFile > mainFile.txt
PS D:\git\tests\mainRepo> echo contentToBeFixed > toBeFixedFile.txt
PS D:\git\tests\mainRepo> echo legacyContent > legacy.txt
PS D:\git\tests\mainRepo> git add -A
PS D:\git\tests\mainRepo> git ci -m "first commit"
PS D:\git\tests\mainRepo> echo firstMainEvol >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "first evol, for making 1.0"
PS D:\git\tests\mainRepo> git tag -m "1.0 legacy content" 1.0
Run Code Online (Sandbox Code Playgroud)

此时,git log --graph --oneline --branches返回:

* b68c1f5 first evol, for making 1.0
* 93f9f7c first commit
Run Code Online (Sandbox Code Playgroud)

让我们建立一个legacy分支

PS D:\git\tests\mainRepo> git co -b legacy
PS D:\git\tests\mainRepo> echo aFirstLegacyEvol >> legacy.txt
PS D:\git\tests\mainRepo> git ci -a -m "a first legacy evolution"
Run Code Online (Sandbox Code Playgroud)

我们回到master,再做一次提交,我们将标记为"2.0"(一个需要修复错误的版本!)

PS D:\git\tests\mainRepo> git co -b master
PS D:\git\tests\mainRepo> git co master
PS D:\git\tests\mainRepo> echo aMainEvol >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a main evol"
PS D:\git\tests\mainRepo> echo aSecondMainEvolFor2.0 >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a second evol for 2.0"
PS D:\git\tests\mainRepo> git tag -m "main 2.0 before bugfix" 2.0
Run Code Online (Sandbox Code Playgroud)

我们有:

* e727105 a second evol for 2.0
* 473d44e a main evol
| * dbcc7aa a first legacy evolution
|/
* b68c1f5 first evol, for making 1.0
* 93f9f7c first commit
Run Code Online (Sandbox Code Playgroud)

现在我们做一个bug10bug修复分支:

PS D:\git\tests\mainRepo> git co -b bug10
PS D:\git\tests\mainRepo> echo aFirstBug10Fix >> toBeFixedFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a first bug10 fix"
PS D:\git\tests\mainRepo> echo aSecondBug10Fix >> toBeFixedFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "a second bug10 fix"
Run Code Online (Sandbox Code Playgroud)

让我们在主分支上添加最终提交

PS D:\git\tests\mainRepo> git co master
PS D:\git\tests\mainRepo> echo anotherMainEvol >> mainFile.txt
PS D:\git\tests\mainRepo> git ci -a -m "another main evol"
Run Code Online (Sandbox Code Playgroud)

我们主要回购的最终状态:

* 55aac85 another main evol
| * 47e6ee1 a second bug10 fix
| * 8183707 a first bug10 fix
|/
* e727105 a second evol for 2.0
* 473d44e a main evol
| * dbcc7aa a first legacy evolution
|/
* b68c1f5 first evol, for making 1.0
* 93f9f7c first commit
Run Code Online (Sandbox Code Playgroud)

在这个阶段,我不会在mainRepo中进行任何进一步的操作.我只会克隆它进行一些测试.如果那些失败,我总是可以回到这个仓库并再次克隆它.

第一个克隆实际上是强制性的,以便执行我们的 git rebase --onto

PS D:\git\tests\mainRepo> cd ..
PS D:\git\tests> git clone mainRepo rebaseRepo
PS D:\git\tests> cd rebaseRepo
Run Code Online (Sandbox Code Playgroud)

我们在克隆的repo中需要两个mainRepo分支:

PS D:\git\tests\rebaseRepo> git co -b bug10 origin/bug10
PS D:\git\tests\rebaseRepo> git co -b legacy origin/legacy
Run Code Online (Sandbox Code Playgroud)

让我们变基只bug10(即毕竟提交2.0标签最多HEADbug10分支):

PS D:\git\tests\rebaseRepo> git co bug10
PS D:\git\tests\rebaseRepo> git rebase --onto legacy 2.0
First, rewinding head to replay your work on top of it...
Applying: a first bug10 fix
Applying: a second bug10 fix
Run Code Online (Sandbox Code Playgroud)

此时bug10已经在legacy 没有所有其他中间提交情况下重播.
我们现在可以快进HEADlegacy把重放的顶部bug10分支.

PS D:\git\tests\rebaseRepo> git co legacy
Switched to branch 'legacy'
PS D:\git\tests\rebaseRepo> git merge bug10
Updating dbcc7aa..cf02bfc
Fast forward
 toBeFixedFile.txt |  Bin 38 -> 104 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)
Run Code Online (Sandbox Code Playgroud)

内容遵循我们的需要:

  • 我们确实拥有所有遗留内容:

 

PS D:\git\tests\rebaseRepo> type legacy.txt
legacyContent
aFirstLegacyEvol
Run Code Online (Sandbox Code Playgroud)

 

  • main分支的内容只有1.0标签(legacy分支的根),而不是任何进一步的.

 

PS D:\git\tests\rebaseRepo> type mainFile.txt
mainFile
firstMainEvol
Run Code Online (Sandbox Code Playgroud)

 

  • bug10修补程序是在这里:

 

PS D:\git\tests\rebaseRepo> type toBeFixedFile.txt
contentToBeFixed
aFirstBug10Fix
aSecondBug10Fix
Run Code Online (Sandbox Code Playgroud)

 

而已.
这个想法是拉的是"增强" legacy分支在原来的回购,这将仍然有其bug10不变(即仍从起始2.0标签,而不是重播任何地方像我们做的rebaseRepo.
在这个克隆的回购协议,我跟踪了origin/legacy分公司,为了在其上合并另一个远程源的legacy分支:.rebaseRepo

PS D:\git\tests\rebaseRepo> cd ..
PS D:\git\tests> git clone mainRepo finalRepo
PS D:\git\tests> cd finalRepo

PS D:\git\tests\finalRepo> git co -b legacy origin/legacy
Run Code Online (Sandbox Code Playgroud)

在这个原始的回购中(我只是克隆它以免弄乱mainRepo的状态,如果我还有其他一些实验要做),我将声明rebaseRepo为远程,并获取其分支.

PS D:\git\tests\finalRepo> git remote add rebasedRepo D:/git/tests/rebaseRepo
PS D:\git\tests\finalRepo> type D:\git\tests\finalRepo\.git\config
[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = D:/git/tests/mainRepo
[branch "master"]
    remote = origin
    merge = refs/heads/master
[branch "legacy"]
    remote = origin
    merge = refs/heads/legacy
[remote "rebasedRepo"]
    url = D:/git/tests/rebaseRepo
    fetch = +refs/heads/*:refs/remotes/rebasedRepo/*

PS D:\git\tests\finalRepo> git fetch rebasedRepo
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 3), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From D:/git/tests/rebaseRepo
 * [new branch]      bug10      -> rebasedRepo/bug10
 * [new branch]      legacy     -> rebasedRepo/legacy
 * [new branch]      master     -> rebasedRepo/master
Run Code Online (Sandbox Code Playgroud)

我们现在可以更新legacy而无需接触bug10:

PS D:\git\tests\finalRepo> git merge rebasedRepo/legacy
Updating dbcc7aa..4919b68
Fast forward
 toBeFixedFile.txt |  Bin 38 -> 104 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)
Run Code Online (Sandbox Code Playgroud)

每当bug10需要在旧legacy分支上重放新提交时,您可以根据需要重复该过程,而不包括所有中间提交.


Miz*_*zor 2

这很难做到。Git 保存合并历史记录,如果你“cherrypick”并指向 bug10101010 中的提交作为父项(表明你已经完成了合并),Git 会假设之前的所有提交(回到它们拆分的点)都已合并为出色地。当您想要进行“真正的”合并时会给您带来问题。

另一方面,您可以从该(且仅该)特定提交手动生成补丁。但是,当您稍后进行“真正的”合并时,这也会给您带来问题,因为它会尝试应用您手动处理的提交两次。

但话又说回来,由于一个分支被命名为“Legacy”,我怀疑您无论如何都不打算进行真正的合并,在这种情况下,您几乎可以自由地按照自己的意愿进行合并。

这是一篇关于该主题的有趣博客文章