简体   繁体   中英

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?

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 , ie, 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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