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

时间:2009-11-12 08:07:03

标签: git branch

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

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

有什么想法吗?

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

3 个答案:

答案 0 :(得分:6)

您应在此处使用 git rebase --onto ,并指定范围 (见git rebase man page

  

将基于一个分支的主题分支移植到另一个分支,假设您使用rebase --onto从后一分支分叉主题分支。

)。

当然,这会将bug10分支移到legacy分支之上,这不是您想要/需要的分支。

因此,一个解决方法是在克隆的回购中执行该rebase,然后合并'增强的'legacy分支(克隆回购中的那个,{{1在其上面进行修改)到本地和当前bug10分支(您要修改的分支,同时单独留下legacy)。

现在:

  • 这涉及额外的回购(可能导致磁盘空间限制)
  • 总而言之,这相当于定义一个补丁并将其应用于bug10分支,因此其他答案(补丁)是有效的(并且更简单)。
  • 我在这种方法中看到的唯一优势就是有机会定义一个遗留环境,在该环境中你可以重新定义你想要的东西(比如legacy提交),然后再将那个分支bug10推送到原来的repo(你不会推legacy,因为它的历史将被完全重写!)

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


bug10

我喜欢我不再拥有git repo目录,然后输入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 Since 1.6.5

  

git init”在给定额外参数(即“git init”)时向mkdir / chdir学习到目录。

这太棒了!

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

git init this

此时,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 返回:

git log --graph --oneline --branches

让我们构建一个* b68c1f5 first evol, for making 1.0 * 93f9f7c first commit 分支

legacy

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

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"

我们有:

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

现在我们做了* 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 错误修复分支:

bug10

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

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"

主要回购的最终状态:

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"

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

第一个克隆实际上是强制性的,以便执行我们的* 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

git rebase --onto

我们需要克隆仓库中的两个mainRepo分支:

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

让我们只修改bug10(这是PS D:\git\tests\rebaseRepo> git co -b bug10 origin/bug10 PS D:\git\tests\rebaseRepo> git co -b legacy origin/legacy 之后提交2.0 HEAD分支的所有提交

bug10

此时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 已在bug10 之上重播,没有所有其他中间提交
我们现在可以将legacy的{​​{1}}快进到重播的HEAD分支的顶部。

legacy

内容遵循我们的需要:

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

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(-) 分支的内容最多只有PS D:\git\tests\rebaseRepo> type legacy.txt legacyContent aFirstLegacyEvol 标记(main分支的根目录),不再进一步

1.0

  • 并且legacy修正在这里:

PS D:\git\tests\rebaseRepo> type mainFile.txt
mainFile
firstMainEvol

就是这样。
我们的想法是在您的原始仓库中提取“增强型”bug10分支,该分支仍然会保持PS D:\git\tests\rebaseRepo> type toBeFixedFile.txt contentToBeFixed aFirstBug10Fix aSecondBug10Fix 不变(即仍然从legacy标记开始,并且不会在任何地方重播我们在bug10上做了 在这个克隆的仓库中,我跟踪2.0分支,以便在其上合并另一个远程源的rebaseRepo分支:origin/legacy

legacy

在这个原始的回购中(我只是将其克隆到不干扰mainRepo的状态,如果我还有其他一些实验要做),我会将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

我们现在可以更新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

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(-) 提交时,您可以根据需要重复该过程,而不包括所有中间提交。

答案 1 :(得分:2)

这很难做到。 Git保存合并历史记录,如果你“cherrypick”并指向bug10101010中的提交作为父级(表明你已完成合并),Git将假定所有提交之前(返回到他们拆分的点)合并为好。当你想进行“真正的”合并时给你带来麻烦。

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

但话又说回来,因为一个分支被命名为“Legacy”,我怀疑你不打算做那个真正的合并,无论如何你都可以自由地做这件事。

继承人interesting blog post on the topic

答案 2 :(得分:1)

使用git-diff然后git-apply