How can I rebase 2 topic branches onto a new branch?

This is the current state of my git repository history:

--o--o--o--o--o--o--o master
            \
             o--o--o--o--o  topic2
                   |
                 topic1

I want to rebase topic1 and topic2 onto master, and make it like:

--o--o--o--o--o--o--o master
                     \
                      o--o--o--o--o  topic2
                            |
                          topic1

What is the best method to achieve this?

  • How do I edit after squashing while doing an interactive rebase?
  • git remove a commit from pull request
  • How to enforce the Git “Do not rebase published commits” rule?
  • Git rebase interactive drop vs deleting the commit line
  • What is wrong with this Git rebasing attempt?
  • Git - Making Changes to Multiple Master Branches
  • Git: fix noobish mistake to avoid rebase hell
  • Missing commits after creating files via GitHub website
  • 3 Solutions collect form web for “How can I rebase 2 topic branches onto a new branch?”

    git rebase master topic2
    git branch -f topic1 HEAD~2   # On (rebased) topic2, set topic1 pointer
    

    Note that this assumes topic1 is simply a pointer to the past of topic2, i.e., there should not be any commits on topic1 that are not on topic2. (The HEAD~2 assumes commit history as shown, in reality you would probably want to use a specific commit id. Note how this would also work if topic1 didn’t even exist: as it has no commits of its “own”, the pointer can just be set arbitrarily.)

    Edit: In this situation, you can alternatively do:

    git rebase master topic1
    git rebase topic1 topic2
    

    The end result should be the same as the first option (iff topic2 contains all of topic1‘s commits!). This syntax may be easier to understand, but the solutions will differ if topic1 does contain commits that are not in topic2. If that is the case the former solution will simply discard any commits in topic1 that are not in topic2, while the latter will merge them into topic2. Both outcomes are probably undesirable, but in my opinion it is more clear from the first solution what will happen, which is why I put it first.

    To illustrate, if your commit history looks like:

    a1 - a2 - a3 - a4 - a5 - a6 - a7 master
                   \
                    b1 - b2 - b3 - b4 - b5 topic2
                              \
                               c1 topic1
    

    Then the first solution (rebase, branch) will give you:

    a1 - a2 - a3 - a4 - a5 - a6 - a7 - b1' - b2' - b3' - b4' - b5' topic2
                                   \ master         \ topic1
    

    And the second (rebase, rebase):

    a1 - a2 - a3 - a4 - a5 - a6 - a7 - b1' - b2' - b3' - c1' - b4' - b5' topic2
                                   \ master               \ topic1
    

    However, in this case what you probably wanted to get was:

    a1 - a2 - a3 - a4 - a5 - a6 - a7 - b1' - b2' - b3' - b4' - b5' topic2
                                   \ master         \
                                                     c1' topic1
    

    The solution for this outcome would be:

    git branch tmp id_of_b3_commit   # In this case id_of_b3_commit == topic1^
    git rebase master tmp
    git rebase tmp topic1
    git rebase tmp topic2
    git branch -d tmp
    

    (If you made this into a script, you could use git merge-base topic1 topic2 to find the id of the commit to put into the tmp branch.)

    If topic 2 is in fact a branch with at least one of it’s own commits, then you can do some grafting. But an easier way to do this is to merge topic 1 and topic 2. Now ‘rebase –onto’ the new place this merged branch with –preserve-merges. Reset topic 1 and topic 2 to where they are supposed to sit.

    You may rebase topic1 and topic2 branches one-by-one.

    Rebase first one

    git checkout topic1
    git rebase master
    

    Then rebase second one

    git checkout topic2
    git rebase master
    

    But i’m not sure what will be with the topic1^ point.

    I suggest to do it in a little bit more complicated way that will preserve branches merge history.

    First make new branch with all commits shared by both topics (you may use commitish or tag instead)

    git checkout -b topics topic1^
    

    Then rebase it on master

    git rebase master
    

    Then rebase both topics on shared branch.

    git checkout topic1
    git rebase topics
    git checkout topic2
    git rebase topics
    

    This should work. Now you may to drop temporary branch.

    git branch -d topics
    
    Git Baby is a git and github fan, let's start git clone.