{"thread":{"id":"15926","subject":"Rebasing Multiple branches at once...","startedAt":"2008-10-16T12:17:20Z","lastAt":"2008-10-17T02:00:41Z","messageCount":9,"participants":["Rick Moynihan","Miklos Vajna","David Kastrup","Robin Burchell","Toby Allsopp","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"93199","messageId":"48F730D0.9040008@calicojack.co.uk","threadId":"15926","inReplyTo":null,"subject":"Rebasing Multiple branches at once...","fromName":"Rick Moynihan","fromEmail":"rick@calicojack.co.uk","sentAt":"2008-10-16T12:17:20Z","receivedAt":"2008-10-16T12:17:20Z","isPatch":false,"sender":{"key":"rick@calicojack.co.uk","avatar":null},"body":"Hi,\n\nI have a master branch, a dev branch and a number of feature branches \nfrom dev.  And I was wondering if there was an easy way to rebase dev \nand all of it's sub-branches onto master.\n\nI know I can run this as a series of commands, and use --onto to do \nthis, but was wondering if there was an easier way.  As running:\n\ngit rebase master\n\nwhen on the dev branch only rebases dev and not it's dependent branches.\n\nThanks!\n\nR.\n"},{"id":"93200","messageId":"20081016135908.GI536@genesis.frugalware.org","threadId":"15926","inReplyTo":"48F730D0.9040008@calicojack.co.uk","subject":"Re: Rebasing Multiple branches at once...","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-10-16T13:59:08Z","receivedAt":"2008-10-16T13:59:08Z","isPatch":false,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Thu, Oct 16, 2008 at 01:17:20PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:\n> I have a master branch, a dev branch and a number of feature branches from \n> dev.  And I was wondering if there was an easy way to rebase dev and all of \n> it's sub-branches onto master.\n\nIn general this is considered harmful. Why do you rebase your branch\nfrom time to time? For example in git.git, topic branches are based on\nmaster, then merged to master when they are ready, but they are never\nrebased.\n"},{"id":"93201","messageId":"8663nsfxoq.fsf@lola.quinscape.zz","threadId":"15926","inReplyTo":"48F730D0.9040008@calicojack.co.uk","subject":"Re: Rebasing Multiple branches at once...","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2008-10-16T13:59:17Z","receivedAt":"2008-10-16T13:59:17Z","isPatch":false,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Rick Moynihan <rick@calicojack.co.uk> writes:\n\n> Hi,\n>\n> I have a master branch, a dev branch and a number of feature branches\n> from dev.  And I was wondering if there was an easy way to rebase dev\n> and all of it's sub-branches onto master.\n>\n> I know I can run this as a series of commands, and use --onto to do\n> this, but was wondering if there was an easier way.  As running:\n>\n> git rebase master\n>\n> when on the dev branch only rebases dev and not it's dependent branches.\n\nRebasing has no relation to dependent branches.  It creates a new branch\nfrom the branch point.  After it finishes, it just reseats HEAD of the\nbranch to the new one.  There is no operation that would work implicitly\non originally dependent branches.\n\n-- \nDavid Kastrup\n"},{"id":"93203","messageId":"48F7542B.1050909@calicojack.co.uk","threadId":"15926","inReplyTo":"20081016135908.GI536@genesis.frugalware.org","subject":"Re: Rebasing Multiple branches at once...","fromName":"Rick Moynihan","fromEmail":"rick@calicojack.co.uk","sentAt":"2008-10-16T14:48:11Z","receivedAt":"2008-10-16T14:48:11Z","isPatch":false,"sender":{"key":"rick@calicojack.co.uk","avatar":null},"body":"Miklos Vajna wrote:\n> On Thu, Oct 16, 2008 at 01:17:20PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:\n>> I have a master branch, a dev branch and a number of feature branches from \n>> dev.  And I was wondering if there was an easy way to rebase dev and all of \n>> it's sub-branches onto master.\n> \n> In general this is considered harmful. Why do you rebase your branch\n> from time to time? For example in git.git, topic branches are based on\n> master, then merged to master when they are ready, but they are never\n> rebased.\n\nYes, but my understanding is that it's only harmful if you publish the \nbranch (or dependent branches) which are being rebased.\n\nSo rebasing is very bad in these circumstances, but I fail to see why \nit's bad if these branches are kept private.\n\n\nR.\n"},{"id":"93205","messageId":"48F75657.6010308@calicojack.co.uk","threadId":"15926","inReplyTo":"8663nsfxoq.fsf@lola.quinscape.zz","subject":"Re: Rebasing Multiple branches at once...","fromName":"Rick Moynihan","fromEmail":"rick@calicojack.co.uk","sentAt":"2008-10-16T14:57:27Z","receivedAt":"2008-10-16T14:57:27Z","isPatch":false,"sender":{"key":"rick@calicojack.co.uk","avatar":null},"body":"David Kastrup wrote:\n> Rick Moynihan <rick@calicojack.co.uk> writes:\n> \n>> Hi,\n>>\n>> I have a master branch, a dev branch and a number of feature branches\n>> from dev.  And I was wondering if there was an easy way to rebase dev\n>> and all of it's sub-branches onto master.\n>>\n>> I know I can run this as a series of commands, and use --onto to do\n>> this, but was wondering if there was an easier way.  As running:\n>>\n>> git rebase master\n>>\n>> when on the dev branch only rebases dev and not it's dependent branches.\n> \n> Rebasing has no relation to dependent branches.  It creates a new branch\n> from the branch point.  After it finishes, it just reseats HEAD of the\n> branch to the new one.  There is no operation that would work implicitly\n> on originally dependent branches.\n\nThis appears to be true of the current implementation, but shouldn't it \nbe possible to do this as a single operation?\n\ne.g. when the situation is this with dev being the current branch.\n\no---o---o---o---o  master\n      \\\n       o---o---o---o---o  dev (*)\n                        \\\n                         o---o---o  topic\n\nRunning the hypothetical command:\n\ngit rebase master --all\n\nWould produce this:\n\no---o---o---o---o  master\n                  \\\n                   o---o---o---o---o  dev (*)\n                                    \\\n                                     o---o---o  topic\n\nI think this can be performed right now with a rebase followed by a \nrebase --onto\n\nI can see how if there were conflicts in the rebase from dev, then you \nwould need to resolve them all the way up your topic branches also.  Is \nthere anything else that makes this a bad idea?\n\nR.\n"},{"id":"93207","messageId":"b19eae4e0810160802x3e91cf48oebe668dc1b6425df@mail.gmail.com","threadId":"15926","inReplyTo":"48F75657.6010308@calicojack.co.uk","subject":"Re: Rebasing Multiple branches at once...","fromName":"Robin Burchell","fromEmail":"w00t@inspircd.org","sentAt":"2008-10-16T15:02:38Z","receivedAt":"2008-10-16T15:02:38Z","isPatch":false,"sender":{"key":"w00t@inspircd.org","avatar":null},"body":"On Thu, Oct 16, 2008 at 3:57 PM, Rick Moynihan <rick@calicojack.co.uk> wrote:\n>\n> This appears to be true of the current implementation, but shouldn't it be\n> possible to do this as a single operation?\n>\n> e.g. when the situation is this with dev being the current branch.\n>\n> o---o---o---o---o  master\n>     \\\n>      o---o---o---o---o  dev (*)\n>                       \\\n>                        o---o---o  topic\n>\n> Running the hypothetical command:\n>\n> git rebase master --all\n>\n> Would produce this:\n>\n> o---o---o---o---o  master\n>                 \\\n>                  o---o---o---o---o  dev (*)\n>                                   \\\n>                                    o---o---o  topic\n>\n> I think this can be performed right now with a rebase followed by a rebase\n> --onto\n>\n> I can see how if there were conflicts in the rebase from dev, then you would\n> need to resolve them all the way up your topic branches also.  Is there\n> anything else that makes this a bad idea?\n>\n> R.\n\n\nRebase is indeed useful IMHO in situations like this with multiple\nrelated topic branches when needing to pull a single fix or two from\nsomewhere without messy merges (especially when that will end up with\nrather a lot of merge commits in history - one or so for each branch,\nwhich is not exactly desirable).\n\n(resent after I learned how to use 'reply to all', sorry Rick)\n"},{"id":"93241","messageId":"87vdvscmkb.fsf@nav-akl-pcn-343.mitacad.com","threadId":"15926","inReplyTo":"48F730D0.9040008@calicojack.co.uk","subject":"Re: Rebasing Multiple branches at once...","fromName":"Toby Allsopp","fromEmail":"toby.allsopp@navman.co.nz","sentAt":"2008-10-16T20:27:48Z","receivedAt":"2008-10-16T20:27:48Z","isPatch":false,"sender":{"key":"toby.allsopp@navman.co.nz","avatar":null},"body":"On Fri, Oct 17 2008, Rick Moynihan wrote:\n\n> Hi,\n>\n> I have a master branch, a dev branch and a number of feature branches\n> from dev.  And I was wondering if there was an easy way to rebase dev\n> and all of it's sub-branches onto master.\n>\n> I know I can run this as a series of commands, and use --onto to do\n> this, but was wondering if there was an easier way.  As running:\n>\n> git rebase master\n>\n> when on the dev branch only rebases dev and not it's dependent\n> branches.\n\nI have a Perl script I use to rebase a number of topic branches as the\nremote tracking branches they're based on move.  It handles the case of\ntopic based on other topics.  It is designed specifically for my\nworkflow, which is tracking a central Subversion repository using\ngit-svn, but I don't think it relies on using git-svn.  Anyway, you\nmight find it useful for inspiration.\n\nThe script outputs a sequence of commands and leaves the running of them\nup to you because you may need to resolve conflicts at any point.\n\nRegards,\nToby.\n\n\n\n#!/usr/bin/perl\n\n# Rebases master and everything based on master to the new trunk.  Use\n# after a git-svn-fetch.\n\nuse strict;\nuse warnings;\n\nuse Getopt::Long;\nuse List::Util qw(first);\n\nuse Git;\n\nmy $dry_run;\n\nGetOptions(\"dry-run|n\" => \\$dry_run)\n  or die \"usage error\";\n\nsub ref2branch {\n    my $ref = shift;\n    $ref =~ s,^refs/heads/,,\n      or die \"Not a branch: '$ref'\";\n    return $ref;\n}\n\nmy $repo = Git->repository();\n\nmy %remotes_by_name;\nmy %remotes_by_hash;\nmy %remote_revs;\n\nfor ($repo->command('for-each-ref', 'refs/remotes')) {\n    my ($hash, undef, $ref) = split;\n    $remotes_by_name{$ref} = $hash;\n    $remotes_by_hash{$hash} = $ref;\n    $remote_revs{$ref} = [$repo->command('rev-list', $ref)];\n}\n\nmy %heads_by_name;\nmy %heads_by_hash;\n\nfor ($repo->command('for-each-ref', 'refs/heads')) {\n    my ($hash, undef, $ref) = split;\n    $heads_by_name{$ref} = $hash;\n    $heads_by_hash{$hash} = $ref;\n}\n\nmy %roots;\nmy %heads_by_parent;\n\nfor my $head (sort keys %heads_by_name) {\n    #print STDERR \"Considering $head\\n\";\n    my $parent;\n    my $last_rev;\n    for my $rev ($repo->command('rev-list', $head, '--not', keys %remotes_by_name)) {\n        my $maybe_parent = $heads_by_hash{$rev};\n        if ($maybe_parent && $maybe_parent ne $head) {\n            #print STDERR \"  found parent $maybe_parent\\n\";\n            $parent = $maybe_parent;\n            last;\n        }\n        $last_rev = $rev;\n    }\n    if ($parent) {\n        push @{$heads_by_parent{$parent}}, $head;\n    } elsif ($last_rev) {\n        my $remote_base = $repo->command_oneline('rev-parse', \"$last_rev^\");\n        my @remotes;\n        #print STDERR \"  last rev $last_rev $remote_base\\n\";\n        for my $remote_name (sort keys %remotes_by_name) {\n            my $remote = first { $_ eq $remote_base } @{$remote_revs{$remote_name}};\n            if (defined($remote) && $remote eq $remote_base) {\n                #print STDERR \"  found remote $remote_name\\n\";\n                push @remotes, $remote_name;\n            }\n        }\n        if (@remotes == 1) {\n            $roots{$head} = $remotes[0];\n        } else {\n            print STDERR \"WARNING: Not exactly one candidate remote for $head: \",\n                join(' ', @remotes), \"\\n\";\n        }\n    }\n}\n\nfor my $root (sort keys %roots) {\n    my $remote = $roots{$root};\n    my $short_root = ref2branch($root);\n    $remote =~ s,^refs/,,;\n    print \"git rebase $remote $short_root\\n\";\n    rebase_tree($root);\n}\n\nsub rebase_tree {\n    my ($parent) = @_;\n    for my $head (@{$heads_by_parent{$parent}}) {\n        my $short_parent = ref2branch($parent);\n        my $short_head = ref2branch($head);\n        print \"git rebase --onto $short_parent $heads_by_name{$parent} $short_head\\n\";\n        rebase_tree($head);\n    }\n}\n"},{"id":"93244","messageId":"20081016210002.GJ536@genesis.frugalware.org","threadId":"15926","inReplyTo":"48F7542B.1050909@calicojack.co.uk","subject":"Re: Rebasing Multiple branches at once...","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-10-16T21:00:02Z","receivedAt":"2008-10-16T21:00:02Z","isPatch":false,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Thu, Oct 16, 2008 at 03:48:11PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:\n> Yes, but my understanding is that it's only harmful if you publish the \n> branch (or dependent branches) which are being rebased.\n> \n> So rebasing is very bad in these circumstances, but I fail to see why it's \n> bad if these branches are kept private.\n\nAh, I thought you publish your branches.\n\nOne reason may be that if you use merge, no history is lost, if you use\nrebase, history is in the reflogs, so it'll be lost after some time. But\nif you know what you are doing, then this is not a problem.\n"},{"id":"93260","messageId":"7vabd4q8ty.fsf@gitster.siamese.dyndns.org","threadId":"15926","inReplyTo":"20081016135908.GI536@genesis.frugalware.org","subject":"Re: Rebasing Multiple branches at once...","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-10-17T02:00:41Z","receivedAt":"2008-10-17T02:00:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Miklos Vajna <vmiklos@frugalware.org> writes:\n\n> On Thu, Oct 16, 2008 at 01:17:20PM +0100, Rick Moynihan <rick@calicojack.co.uk> wrote:\n>> I have a master branch, a dev branch and a number of feature branches from \n>> dev.  And I was wondering if there was an easy way to rebase dev and all of \n>> it's sub-branches onto master.\n>\n> In general this is considered harmful. Why do you rebase your branch\n> from time to time? For example in git.git, topic branches are based on\n> master, then merged to master when they are ready, but they are never\n> rebased.\n\nI do not think it is harmful per-se as long as they are not published.\n\nBut rebasing topic branches regularly (i.e. without reasons better than\n\"the master has more commits than before\") is _pointless_.  The whole\npoint of a topic branch is to house the development related to one single\ntopic.  If you keep rebasing it, its progress (when you look at the\ndifferences between topic@{1} and topic, topic@{2} and topic@{1}, ...)\nwould not be about the single topic, but about the single topic _and\nall the other random things that happened on the master branch_.\n\nWhen you merge a topic branch that forked from an older version of\n'master', you may have conflicts, and you may want to resolve it earlier\nand that might be why you would want to rebase.  But if you _know_ you are\ngoing to have conflicts, you wouldn't wish to rebase all of them at once\nto begin with, as you would need to resolve such conflicts yourself\nanyway.  On the other hand, if you expect there won't be any conflict,\nthen there absolutely is no point in rebasing them.  If you want to make\nsure that your topics would all work with the updated 'master', you are\nmuch better off creating trial tree, merging your topics on top of the\nupdated 'master' one by one, than rebasing all of your topic branches.\n"}]}