Gautam Jethwani
Gautam Jethwani

Reputation: 191

How to merge a parent branch while keeping the child branch intact

I currently have a branch off of master which, for the purposes of this question, we will call "branch A". I want to develop a new feature that builds on code that I wrote in branch A but it's a significant feature so I want to make a new branch. Let's call this new branch "branch B". I need to start working on branch B now but branch A will be merged to master at some point after branch B is created but before branch B is finished. Is there a way to do this so that the branch hierarchy is preserved? Here's a visualisation of what I want:

Before merge:

_______ master
  \________ branch A
       \________ branch B

After merge:

_______ master (with branch A merged)
   \_______ branch B

I essentially want my branch structure to remain intact but move up a level.

This is what I don't want to happen:

Before merge:

_______ master
  \________ branch A
       \________ branch B

After merge:

_______ master (with both branch A and branch B merged)

Is there a way to make this happen?

Upvotes: 6

Views: 2836

Answers (1)

Romain Valeri
Romain Valeri

Reputation: 22067

Yes, it can be done very easily since it's the principle of merge in action here.


What to do?

Just merge branchA into master, branchB will stay out of the scope of this merge.

git checkout master
git merge branchA

Why?

Git will search for the merge-base between these two (the most recent commit they share) then apply to the receiving end (here master) every commit present in the giving end (here branchA) that master does not have.

Let's imagine a more detailed example around yours :

C1-<-C2-<-C3-<-C4 <<< master
      \
       \
        C5-<-C6-<-C7-<-C8 <<< branchA
                   \
                    \
                     C9-<-C10 <<< branchB

When you do git merge branchA from your master branch, git will determine that the merge-base between these two branches is C2. Then it will detect C5, C6, C7 and C8 as the commits absent from master but present in branchA. C9 and C10 have no reason to be included since they're not reachable from branchA.


Situation afterwards

C1-<-C2-<-C3-<-C4-<--------C11 <<< master
      \                   /
       \                 /
        C5-<-C6-<-C7-<-C8 <<< branchA
                   \
                    \
                     C9-<-C10 <<< branchB

You could or not dispose of your branchA after the merge, but in any case master will contain* every commit but C9 and C10. (C11 is the merge commit.)

And you'll be able to go on working on branchB then merge it into master (or not, for that matter) at some future point.

* (some people prefer this metaphor to conceptualize branches, but technically it just means that all these commits are reachable from the branch tip, through parent relation)

Upvotes: 7

Related Questions