# Rebasing Multiple branches at once...

9 messages from 2008-10-16 to 2008-10-17. Participants: Rick Moynihan, Miklos Vajna, David Kastrup, Robin Burchell, Toby Allsopp, Junio C Hamano.
Thread: https://gitlist.dev/t/15926

## Rick Moynihan, 2008-10-16 12:17

Subject: Rebasing Multiple branches at once...
Message-ID: <48F730D0.9040008@calicojack.co.uk>
URL: https://gitlist.dev/e/48F730D0.9040008%40calicojack.co.uk

```
Hi,

I have a master branch, a dev branch and a number of feature branches 
from dev.  And I was wondering if there was an easy way to rebase dev 
and all of it's sub-branches onto master.

I know I can run this as a series of commands, and use --onto to do 
this, but was wondering if there was an easier way.  As running:

git rebase master

when on the dev branch only rebases dev and not it's dependent branches.

Thanks!

R.

```

## Miklos Vajna, 2008-10-16 13:59

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <20081016135908.GI536@genesis.frugalware.org>
URL: https://gitlist.dev/e/20081016135908.GI536%40genesis.frugalware.org
In-Reply-To: <48F730D0.9040008@calicojack.co.uk>

```
On Thu, Oct 16, 2008 at 01:17:20PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:
> I have a master branch, a dev branch and a number of feature branches from 
> dev.  And I was wondering if there was an easy way to rebase dev and all of 
> it's sub-branches onto master.

In general this is considered harmful. Why do you rebase your branch
from time to time? For example in git.git, topic branches are based on
master, then merged to master when they are ready, but they are never
rebased.

```

## David Kastrup, 2008-10-16 13:59

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <8663nsfxoq.fsf@lola.quinscape.zz>
URL: https://gitlist.dev/e/8663nsfxoq.fsf%40lola.quinscape.zz
In-Reply-To: <48F730D0.9040008@calicojack.co.uk>

```
Rick Moynihan <rick@calicojack.co.uk> writes:

> Hi,
>
> I have a master branch, a dev branch and a number of feature branches
> from dev.  And I was wondering if there was an easy way to rebase dev
> and all of it's sub-branches onto master.
>
> I know I can run this as a series of commands, and use --onto to do
> this, but was wondering if there was an easier way.  As running:
>
> git rebase master
>
> when on the dev branch only rebases dev and not it's dependent branches.

Rebasing has no relation to dependent branches.  It creates a new branch
from the branch point.  After it finishes, it just reseats HEAD of the
branch to the new one.  There is no operation that would work implicitly
on originally dependent branches.

-- 
David Kastrup

```

## Rick Moynihan, 2008-10-16 14:48

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <48F7542B.1050909@calicojack.co.uk>
URL: https://gitlist.dev/e/48F7542B.1050909%40calicojack.co.uk
In-Reply-To: <20081016135908.GI536@genesis.frugalware.org>

```
Miklos Vajna wrote:
> On Thu, Oct 16, 2008 at 01:17:20PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:
>> I have a master branch, a dev branch and a number of feature branches from 
>> dev.  And I was wondering if there was an easy way to rebase dev and all of 
>> it's sub-branches onto master.
> 
> In general this is considered harmful. Why do you rebase your branch
> from time to time? For example in git.git, topic branches are based on
> master, then merged to master when they are ready, but they are never
> rebased.

Yes, but my understanding is that it's only harmful if you publish the 
branch (or dependent branches) which are being rebased.

So rebasing is very bad in these circumstances, but I fail to see why 
it's bad if these branches are kept private.


R.

```

## Rick Moynihan, 2008-10-16 14:57

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <48F75657.6010308@calicojack.co.uk>
URL: https://gitlist.dev/e/48F75657.6010308%40calicojack.co.uk
In-Reply-To: <8663nsfxoq.fsf@lola.quinscape.zz>

```
David Kastrup wrote:
> Rick Moynihan <rick@calicojack.co.uk> writes:
> 
>> Hi,
>>
>> I have a master branch, a dev branch and a number of feature branches
>> from dev.  And I was wondering if there was an easy way to rebase dev
>> and all of it's sub-branches onto master.
>>
>> I know I can run this as a series of commands, and use --onto to do
>> this, but was wondering if there was an easier way.  As running:
>>
>> git rebase master
>>
>> when on the dev branch only rebases dev and not it's dependent branches.
> 
> Rebasing has no relation to dependent branches.  It creates a new branch
> from the branch point.  After it finishes, it just reseats HEAD of the
> branch to the new one.  There is no operation that would work implicitly
> on originally dependent branches.

This appears to be true of the current implementation, but shouldn't it 
be possible to do this as a single operation?

e.g. when the situation is this with dev being the current branch.

o---o---o---o---o  master
      \
       o---o---o---o---o  dev (*)
                        \
                         o---o---o  topic

Running the hypothetical command:

git rebase master --all

Would produce this:

o---o---o---o---o  master
                  \
                   o---o---o---o---o  dev (*)
                                    \
                                     o---o---o  topic

I think this can be performed right now with a rebase followed by a 
rebase --onto

I can see how if there were conflicts in the rebase from dev, then you 
would need to resolve them all the way up your topic branches also.  Is 
there anything else that makes this a bad idea?

R.

```

## Robin Burchell, 2008-10-16 15:02

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <b19eae4e0810160802x3e91cf48oebe668dc1b6425df@mail.gmail.com>
URL: https://gitlist.dev/e/b19eae4e0810160802x3e91cf48oebe668dc1b6425df%40mail.gmail.com
In-Reply-To: <48F75657.6010308@calicojack.co.uk>

```
On Thu, Oct 16, 2008 at 3:57 PM, Rick Moynihan <rick@calicojack.co.uk> wrote:
>
> This appears to be true of the current implementation, but shouldn't it be
> possible to do this as a single operation?
>
> e.g. when the situation is this with dev being the current branch.
>
> o---o---o---o---o  master
>     \
>      o---o---o---o---o  dev (*)
>                       \
>                        o---o---o  topic
>
> Running the hypothetical command:
>
> git rebase master --all
>
> Would produce this:
>
> o---o---o---o---o  master
>                 \
>                  o---o---o---o---o  dev (*)
>                                   \
>                                    o---o---o  topic
>
> I think this can be performed right now with a rebase followed by a rebase
> --onto
>
> I can see how if there were conflicts in the rebase from dev, then you would
> need to resolve them all the way up your topic branches also.  Is there
> anything else that makes this a bad idea?
>
> R.


Rebase is indeed useful IMHO in situations like this with multiple
related topic branches when needing to pull a single fix or two from
somewhere without messy merges (especially when that will end up with
rather a lot of merge commits in history - one or so for each branch,
which is not exactly desirable).

(resent after I learned how to use 'reply to all', sorry Rick)

```

## Toby Allsopp, 2008-10-16 20:27

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <87vdvscmkb.fsf@nav-akl-pcn-343.mitacad.com>
URL: https://gitlist.dev/e/87vdvscmkb.fsf%40nav-akl-pcn-343.mitacad.com
In-Reply-To: <48F730D0.9040008@calicojack.co.uk>

```
On Fri, Oct 17 2008, Rick Moynihan wrote:

> Hi,
>
> I have a master branch, a dev branch and a number of feature branches
> from dev.  And I was wondering if there was an easy way to rebase dev
> and all of it's sub-branches onto master.
>
> I know I can run this as a series of commands, and use --onto to do
> this, but was wondering if there was an easier way.  As running:
>
> git rebase master
>
> when on the dev branch only rebases dev and not it's dependent
> branches.

I have a Perl script I use to rebase a number of topic branches as the
remote tracking branches they're based on move.  It handles the case of
topic based on other topics.  It is designed specifically for my
workflow, which is tracking a central Subversion repository using
git-svn, but I don't think it relies on using git-svn.  Anyway, you
might find it useful for inspiration.

The script outputs a sequence of commands and leaves the running of them
up to you because you may need to resolve conflicts at any point.

Regards,
Toby.



#!/usr/bin/perl

# Rebases master and everything based on master to the new trunk.  Use
# after a git-svn-fetch.

use strict;
use warnings;

use Getopt::Long;
use List::Util qw(first);

use Git;

my $dry_run;

GetOptions("dry-run|n" => \$dry_run)
  or die "usage error";

sub ref2branch {
    my $ref = shift;
    $ref =~ s,^refs/heads/,,
      or die "Not a branch: '$ref'";
    return $ref;
}

my $repo = Git->repository();

my %remotes_by_name;
my %remotes_by_hash;
my %remote_revs;

for ($repo->command('for-each-ref', 'refs/remotes')) {
    my ($hash, undef, $ref) = split;
    $remotes_by_name{$ref} = $hash;
    $remotes_by_hash{$hash} = $ref;
    $remote_revs{$ref} = [$repo->command('rev-list', $ref)];
}

my %heads_by_name;
my %heads_by_hash;

for ($repo->command('for-each-ref', 'refs/heads')) {
    my ($hash, undef, $ref) = split;
    $heads_by_name{$ref} = $hash;
    $heads_by_hash{$hash} = $ref;
}

my %roots;
my %heads_by_parent;

for my $head (sort keys %heads_by_name) {
    #print STDERR "Considering $head\n";
    my $parent;
    my $last_rev;
    for my $rev ($repo->command('rev-list', $head, '--not', keys %remotes_by_name)) {
        my $maybe_parent = $heads_by_hash{$rev};
        if ($maybe_parent && $maybe_parent ne $head) {
            #print STDERR "  found parent $maybe_parent\n";
            $parent = $maybe_parent;
            last;
        }
        $last_rev = $rev;
    }
    if ($parent) {
        push @{$heads_by_parent{$parent}}, $head;
    } elsif ($last_rev) {
        my $remote_base = $repo->command_oneline('rev-parse', "$last_rev^");
        my @remotes;
        #print STDERR "  last rev $last_rev $remote_base\n";
        for my $remote_name (sort keys %remotes_by_name) {
            my $remote = first { $_ eq $remote_base } @{$remote_revs{$remote_name}};
            if (defined($remote) && $remote eq $remote_base) {
                #print STDERR "  found remote $remote_name\n";
                push @remotes, $remote_name;
            }
        }
        if (@remotes == 1) {
            $roots{$head} = $remotes[0];
        } else {
            print STDERR "WARNING: Not exactly one candidate remote for $head: ",
                join(' ', @remotes), "\n";
        }
    }
}

for my $root (sort keys %roots) {
    my $remote = $roots{$root};
    my $short_root = ref2branch($root);
    $remote =~ s,^refs/,,;
    print "git rebase $remote $short_root\n";
    rebase_tree($root);
}

sub rebase_tree {
    my ($parent) = @_;
    for my $head (@{$heads_by_parent{$parent}}) {
        my $short_parent = ref2branch($parent);
        my $short_head = ref2branch($head);
        print "git rebase --onto $short_parent $heads_by_name{$parent} $short_head\n";
        rebase_tree($head);
    }
}

```

## Miklos Vajna, 2008-10-16 21:00

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <20081016210002.GJ536@genesis.frugalware.org>
URL: https://gitlist.dev/e/20081016210002.GJ536%40genesis.frugalware.org
In-Reply-To: <48F7542B.1050909@calicojack.co.uk>

```
On Thu, Oct 16, 2008 at 03:48:11PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:
> Yes, but my understanding is that it's only harmful if you publish the 
> branch (or dependent branches) which are being rebased.
> 
> So rebasing is very bad in these circumstances, but I fail to see why it's 
> bad if these branches are kept private.

Ah, I thought you publish your branches.

One reason may be that if you use merge, no history is lost, if you use
rebase, history is in the reflogs, so it'll be lost after some time. But
if you know what you are doing, then this is not a problem.

```

## Junio C Hamano, 2008-10-17 02:00

Subject: Re: Rebasing Multiple branches at once...
Message-ID: <7vabd4q8ty.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vabd4q8ty.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <20081016135908.GI536@genesis.frugalware.org>

```
Miklos Vajna <vmiklos@frugalware.org> writes:

> On Thu, Oct 16, 2008 at 01:17:20PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:
>> I have a master branch, a dev branch and a number of feature branches from 
>> dev.  And I was wondering if there was an easy way to rebase dev and all of 
>> it's sub-branches onto master.
>
> In general this is considered harmful. Why do you rebase your branch
> from time to time? For example in git.git, topic branches are based on
> master, then merged to master when they are ready, but they are never
> rebased.

I do not think it is harmful per-se as long as they are not published.

But rebasing topic branches regularly (i.e. without reasons better than
"the master has more commits than before") is _pointless_.  The whole
point of a topic branch is to house the development related to one single
topic.  If you keep rebasing it, its progress (when you look at the
differences between topic@{1} and topic, topic@{2} and topic@{1}, ...)
would not be about the single topic, but about the single topic _and
all the other random things that happened on the master branch_.

When you merge a topic branch that forked from an older version of
'master', you may have conflicts, and you may want to resolve it earlier
and that might be why you would want to rebase.  But if you _know_ you are
going to have conflicts, you wouldn't wish to rebase all of them at once
to begin with, as you would need to resolve such conflicts yourself
anyway.  On the other hand, if you expect there won't be any conflict,
then there absolutely is no point in rebasing them.  If you want to make
sure that your topics would all work with the updated 'master', you are
much better off creating trial tree, merging your topics on top of the
updated 'master' one by one, than rebasing all of your topic branches.

```
