Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rebase many branches (with the same base commit) at once?

I have a master branch in my project, that I use to pull changes from other people. From that, I usually have several topic branches on which I'm currently working.

My question is: Is there a way for me to pull new changes into my master and then rebase ALL of my topic branches onto that at once?

This is the situation:

        D--E topic1        / A--B--C master        \         F--G topic2 

And I want to accomplish this with one single command (H came from upstream) :

                D'--E' topic1               /     A--B--C--H master               \                F'--G' topic2 

Now, I know I can accomplish this by rebasing topic1 and topic2 onto master, and I could even write a script to automate this. But what if I have several other branches, create new ones and delete others frequently and I receive upstream changes all the time?

This operation (several rebases), when done by hand, is both tiring and error-prone.

Is there an easier way?

like image 711
malvim Avatar asked May 14 '09 22:05

malvim


People also ask

Can I rebase multiple branches?

Git merge and rebase serve the same purpose. They are designed to integrate changes from one or multiple branches into one. Although the final goal is the same, those two methods achieve it in different ways, and it's helpful to know the difference. Let's start with the following graph to understand the differences.

Can you rebase more than once?

Yes, you can rebase more than once. After rebasing, you get a fresh set of commits. These commits are exactly like all other commits and hold no record of having been rebased. The main thing you need to be careful for is the possibility of rebase conflicts.

Is merge better than rebase?

For individuals, rebasing makes a lot of sense. If you want to see the history completely same as it happened, you should use merge. Merge preserves history whereas rebase rewrites it . Rebasing is better to streamline a complex history, you are able to change the commit history by interactive rebase.


2 Answers

I'm fairly sure that there isn't a way to automatically do this. Remember that "git rebase master" can also drop you back to the shell needing you to resolve merge conflicts, so if you want to write a script to automate all this you need to take that into account.

You can fairly easily track which branches need updating, though. Hmm, for any branch, "git rev-list branch..master" will produce output if the branch is not up-to-date wrt (i.e. just commits on top of) master. So you need to loop through all the local heads except master to produce a report (nb "git show-branch" will approximately do this):

git for-each-ref 'refs/heads/*' | \   while read rev type ref; do     branch=$(expr "$ref" : 'refs/heads/\(.*\)' )     revs=$(git rev-list $rev..master)     if [ -n "$revs" ]; then       echo $branch needs update       git diff --summary --shortstat -M -C -C $rev master     fi   done 

So if you were feeling brave, you could replace that "git diff" with something like "git checkout $branch && git rebase master" (or maybe just "git pull --rebase" if you've set that up). I think you'd then have to check for the existence of a ".git/rebase-apply" directory or check the index for unmerged files ("git ls-files -u") to test if we've been left waiting to do a merge.

Of course, if there are no conflicts, then it's easy... it's producing something that also works when it's not easy that's the problem :p

And this doesn't necessarily address what happens if one of your branches is based on something else... that's why I mentioned using "git pull --rebase" instead, because that would rebase according to the branch configuration, not blindly from master. Although the detection isn't based on the branch configuration... maybe it would be easiest just to check out each branch and do "git pull" and let the branch configuration handle everything, including whether to rebase or merge?

like image 147
araqnid Avatar answered Sep 20 '22 13:09

araqnid


You can always just write a shell one-liner like this:

for branch in topic1 topic2 topic3;do git rebase master $branch;done 

Since the topic branches you would like to rebase will probably change over time, this is a quick-and-dir^H^H^Hflexible solution :-)

like image 39
flacs Avatar answered Sep 19 '22 13:09

flacs