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

19,943

Solution 1

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?

Solution 2

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 :-)

Solution 3

I have turned this into a robust script, maintained in my git-extensions repository:

$ git-urebaselocalbr --help
Rebase all / the last committed N local branches (except for the current branch
and master) to the updated upstream head.
Usage: git-urebaselocalbr [--continue|--skip|--abort] [--branches "<branch1> ..."] [N] [-i|--interactive] [options]
Share:
19,943
malvim
Author by

malvim

Updated on June 09, 2022

Comments

  • malvim
    malvim about 2 years

    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?

  • malvim
    malvim about 15 years
    Thanks for the help! I guess this is just a harder problem than I thought it was, so I'll keep going by with manual rebasing. :)
  • rjmunro
    rjmunro about 14 years
    I use git branch --no-merged to list the branches that I want to bring up to the latest master.
  • araqnid
    araqnid about 14 years
    @rjmunro nice, I didn't know about that flag. However, I don't think it's appropriate for the case where your branches need rebasing rather than merging.
  • kynan
    kynan about 12 years
    See this answer to a related question for a "smarter" version, automatically determining branches containing a particular base commit.
  • Amit Verma
    Amit Verma over 3 years
    While this code may provide a solution to the question, it's better to add context as to why/how it works. This can help future users learn and eventually apply that knowledge to their own code. You are also likely to have positive-feedback/upvotes from users, when the code is explained.