How to merge a branch into 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 am not going to merge bug10101010 into main. So far so good. Now I have another branch of the same product called legacy. I do not want to combine bug10101010 with a child branch in GIT.

Any ideas?

I can’t just merge it directly, since the bug10101010 branch is detached from the main branch, and in the inheritance I only need diff between the bug10101010 branch and its parent branch.

+6
git branch
source share
3 answers

This is hard to do. Git saves the merge history, and if you "cherrypick" and point to the commit in bug10101010 as the parent (indicating that you did the merge), Git will assume that everything is done before (back to the point where they split) as it was merged. Giving you problems when you want to do a "real" merge.

On the other hand, you can simply manually create a patch from this (and only that) specific commit. But it will also give you problems when you later perform a “real” merge, as it tries to apply your manual transaction twice.

But then again, since one branch is called "Legacy", I suspect that you still do not plan to do this real merge, in which case you can pretty much do it anyway, please.

Heres a interesting related blog post .

+2
source share

Here you should use git rebase --onto and specify a range.
(see git rebase man page :

transplant a topic branch based on one branch to another to pretend that you are forking a topic branch from the last branch using rebase --onto .

)

Of course, this will move your bug10 branch over the legacy branch, which does not fit your needs.

Thus, one way would be to do this reboot in the cloned repo, and then merge this extended legacy branch (the one in the cloning repository, with bug10 to) for the local and current legacy branch (the one you want to change, leaving bug10 only).

Now:

  • this is due to an additional repo (which may lead to limited disk space)
  • in general, this is quite equivalent to defining a patch and applying it to the legacy branch, so that the other answers (patch) are valid (and easier).
  • The only advantage that I see in this method is the ability to define an outdated environment in which you reinstall what you want (e.g. bug10 ) before pushing only this legacy branch to the original repo (you do not bug10 since it the story would be completely rewritten!)

I just wanted to see if it works, so ... Let me check this approach.
(Git1.6.5.1, on old XP SP2, with Powershell 1.0 session due to Start-Transcript command)


 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 no longer need to make a git repo directory, and then type git init ! Starting from version 1.6.5 :

" git init " learned mkdir / chdir in the directory when it was given an additional argument (ie, " git init this ").

This is BIG!

Let me create 3 files for three different purposes.
(For an example, I will store file changes separately for each branch: no conflicts during merge or redirection here.)

 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:

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

Let build legacy branch

 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 will return to the wizard, make another commit, which we will mark "2.0" (release, which will require bug fixes!)

 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 create the 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" 

Add add final commit on 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 point, I will not do any further manipulations in mainRepo. I will only clone it to do some tests. If this fails, I can always go back to this repo and clone it again.

The first clone is actually required to execute our git rebase --onto

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

In our cloned repo, we need two mainRepo branches:

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

Allows you to reinstall only error10 (this is all fixed after the 2.0 tag to the HEAD branch of 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 

At this point, bug10 was played on top of legacy without any other intermediate commits .
Now we can forward HEAD from legacy to the beginning of the replayed bug10 branch.

 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 corresponds to what we need:

  • We have all the outdated content:

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

  • for the main branch, there is only a 1.0 tag (root for the legacy branch) and no more .

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

  • and bug10 fixes are here:

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

What is it.
The idea is to pull this “extended” legacy branch into your original repo, which will still remain without bug10 (i.e., still starting with the 2.0 tag and not being replayed anywhere, as we did on rebaseRepo .
In this cloned repo, I track the origin/legacy branch to merge the legacy branch of another remote source on it: 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 so as not to mess with the state of mainRepo, in case I had other experiments), I will rebaseRepo as remote and select its branches.

 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 

Now we can update legacy without touching 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(-) 

You can repeat the process as many times as you want, whenever you need to run a new bug10 , you need to replay over the old legacy branch, not including all intermediate commits.

+6
source share

Use git-diff and then git-apply ?

+1
source share

All Articles