简体   繁体   English

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

[英]How to merge a branch to another branch in GIT?

Let me explain the problem in detail. 让我详细解释一下这个问题。

I have a main git branch on which I created a new side branch bug10101010, now I wan't to merge the bug10101010 to main. 我有一个主git分支,我在其上创建了一个新的side branch bug10101010,现在我不想将bug10101010合并到main。 So far everything is good. 到目前为止一切都很好。 Now I have a different branch of the same product, named legacy. 现在我有一个相同产品的不同分支,名为legacy。 I wan't to merge the bug10101010 to the legacy branch in GIT. 我不想将bug10101010合并到GIT中的遗留分支。

Any ideas? 有任何想法吗?

I can't just merge it directly, as the branch bug10101010 is spin off from the main branch and in the legacy I need only the diff between the branch bug10101010 and its parent branch. 我不能直接合并它,因为分支bug10101010是从主分支中分离的,而在遗产中我只需要分支bug10101010与其父分支之间的差异。

You should use git rebase --onto here, and specify a range. 你应该在这里使用git rebase --onto ,并指定一个范围。
(see git rebase man page : (参见git rebase手册页

transplant a topic branch based on one branch to another, to pretend that you forked the topic branch from the latter branch, using rebase --onto . 将基于一个分支的主题分支移植到另一个分支,假装您使用rebase --onto从后一个分支分叉主题分支。

). )。

Of course, this would move your bug10 branch on top of the legacy branch, which is not what you want/need. 当然,这会将你的bug10分支移到legacy分支之上,这不是你想要/需要的。

So, one workaround would be to do that rebase in a cloned repo, then merge that 'enhanced' legacy branch (the one in the clone repo, with the bug10 modifications on top of it) to the local and current legacy branch (the one you want to modify, while leaving bug10 alone). 因此,一个解决方法是在克隆的repo中进行rebase,然后将“增强的” legacy分支 (克隆repo中的bug10 ,其上面的bug10修改) bug10 到本地和当前的legacy分支 (一个)你想修改,同时留下bug10 )。

Now: 现在:

  • this involves an extra repo (which can lead to disk space limitation) 这涉及额外的回购(可能导致磁盘空间限制)
  • all in all, this is fairly equivalent to define a patch and apply it to legacy branch, so the other answers (patch) are valid (and simpler). 总而言之,这相当于定义一个补丁并将其应用于legacy分支,因此其他答案(补丁)是有效的(并且更简单)。
  • the only advantage I see in this method is the opportunity to define a legacy environment in which you rebase what you want (like the bug10 commits), before pushing only that branch legacy to your original repo (you would not push bug10 , since its history would have been entirely rewritten!) 我在这种方法中看到的唯一优势就是有机会定义一个遗留环境,你可以在其中重新定义你想要的东西(比如bug10提交),然后再将那个分支legacy推送到你的原始bug10 (你不会推动bug10 ,因为它的历史本来应该完全改写!)

I just wanted to see if it works, so... Let's test that approach. 我只想看看它是否有效,所以......让我们测试一下这种方法。
(Git1.6.5.1, on a old XP SP2, with a Powershell 1.0 session because of the Start-Transcript command ) (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

I like how I do not have anymore to make the git repo directory first, then type in it git init ! 我喜欢我不再拥有git repo目录,然后输入git init Since 1.6.5 : 从1.6.5开始

" git init " learned to mkdir / chdir into a directory when given an extra argument (ie " git init this "). 当给出一个额外的参数(即“ git init this ”)时,“ git init ”学会了mkdir / chdir到一个目录中。

This is GREAT! 这很棒!

Let's create 3 files, for 3 different purposes. 让我们创建3个文件,用于3种不同的目的。
(For the sake of example, I will keep the file modifications separate per branch: no conflict during merge or rebase here.) (为了示例,我将保持每个分支的文件修改:在合并或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

At this point, a git log --graph --oneline --branches returns: 此时, git log --graph --oneline --branches返回:

* b68c1f5 first evol, for making 1.0
* 93f9f7c first commit

Let's build a legacy branch 让我们构建一个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"

We return to master, make another commit, which we will tag "2.0" (a release which will need some bug-fixing!) 我们回到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

We have: 我们有:

* 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

Now we do a bug10 bug-fixing branch: 现在我们做一个bug10 bug修复分支:

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"

Let's add a final commit on the main branch 让我们在主分支上添加最终提交

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"

Final state of our main repo: 我们主要回购的最终状态:

* 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

At this stage, I will not make any further manipulation in mainRepo. 在这个阶段,我不会在mainRepo中进行任何进一步的操作。 I will only clone it to make some tests. 我只会克隆它进行一些测试。 If those fails, I can always get back to this repo and clone it again. 如果那些失败,我总是可以回到这个仓库并再次克隆它。

The first clone is actually mandatory, in order to perform our git rebase --onto 第一个克隆实际上是强制性的,以便执行我们的git rebase --onto

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

We need two of the mainRepo branches in our cloned repo: 我们在克隆的repo中需要两个mainRepo分支:

PS D:\git\tests\rebaseRepo> git co -b bug10 origin/bug10
PS D:\git\tests\rebaseRepo> git co -b legacy origin/legacy

Let's rebase only bug10 (that is all commits after 2.0 tag up to HEAD of bug10 branch) : 让我们只修改bug10(这是在2.0标签之后的所有提交到bug10分支的HEAD

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

At this point bug10 has been replayed on top of legacy without all the other intermediate commits . 此时bug10已经在legacy上重放, 没有所有其他中间提交
We can now fast-forward HEAD of legacy to the top of the replayed bug10 branch. 我们现在可以将legacy HEAD快速转发到重放的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(-)

The content follow what we need: 内容遵循我们的需要:

  • We do have all the legacy content: 我们确实拥有所有遗留内容:

PS D:\git\tests\rebaseRepo> type legacy.txt
legacyContent
aFirstLegacyEvol

  • the content for the main branch is there only up to 1.0 tag (root for legacy branch), and not any further . main分支的内容最多只有1.0标签( legacy分支的根目录),而不是更多

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

  • and the bug10 fixes are here: bug10修复程序在这里:

PS D:\git\tests\rebaseRepo> type toBeFixedFile.txt
contentToBeFixed
aFirstBug10Fix
aSecondBug10Fix

That's it. 而已。
The idea is to to pull that 'enhanced' legacy branch in your original repo, which will still have its bug10 unchanged (ie still starting from the 2.0 tag, and not replayed anywhere like we did on the rebaseRepo . 我们的想法是在您的原始bug10提取“增强型” legacy分支,这仍将使其bug10保持不变(即仍然从2.0标记开始,并且不像我们在rebaseRepo上那样重放任何地方。
In this cloned repo, I track the origin/legacy branch, in order to merge on it the legacy branch of another remote source: the 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

In this original repo (I only cloned it to not mess with the state of the mainRepo, in case I had some other experiments to do), I will declare rebaseRepo as a remote, and fetch its branches. 在这个原始的repo中(我只是克隆它不会弄乱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

We can now update legacy without touching to bug10 : 我们现在可以在不触及bug10情况下更新legacy

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(-)

You can repeat the process as many time as you want, whenever new bug10 commits need to be replayed on top of an old legacy branch, without including all the intermediate commits. 每当需要在旧的legacy分支上重放新的bug10提交时,您可以根据需要重复该过程,而不包括所有中间提交。

This is hard to do. 这很难做到。 Git saves merge history, and if you "cherrypick" and point at a commit in bug10101010 as a parent (indicating you have done a merge) Git will assume that all commits before that (back to the point where they split) as been merged as well. Git保存合并历史记录,如果你“cherrypick”并指向bug10101010中的提交作为父级(表明你已完成合并),Git将假定所有提交之前(返回到他们拆分的点)合并为好。 Giving you problems when you want to do a "real" merge. 当你想进行“真正的”合并时,给你带来麻烦。

On the other hand you can just manually generate a patch from that (and only that) specific commit. 另一方面,您可以从该(并且仅限于)特定提交手动生成补丁。 But that will also give you problems when you later do the "real" merge, since it tries to apply your manually handled commit twice. 但是,当您稍后进行“真正的”合并时,这也会给您带来问题,因为它会尝试两次应用您手动处理的提交。

But then again, since one branch is named "Legacy" I suspect that you dont plan to do that real merge anyway, in which case youre pretty much free to do it anyway you please. 但话说回来,因为一个分支被命名为“Legacy”,我怀疑你不打算做那个真正的合并,在这种情况下,无论如何你都可以自由地做它。

Heres an interesting blog post on the topic . 这是一篇关于这个主题有趣博客文章

使用git-diff然后git-apply

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM