{"thread":{"id":"22515","subject":"rebase vs rebase -i","startedAt":"2010-02-04T04:19:24Z","lastAt":"2010-02-05T01:20:53Z","messageCount":10,"participants":["Jay Soffian","Johannes Schindelin","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"133584","messageId":"76718491002032019i5f8ea947paa527988ddb7a378@mail.gmail.com","threadId":"22515","inReplyTo":null,"subject":"rebase vs rebase -i","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2010-02-04T04:19:24Z","receivedAt":"2010-02-04T04:19:24Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"Why does git rebase use format-patch + am, while rebase -i uses cherry-pick?\n\nJust curious. In particular though, it seems especially odd in this case:\n\n$ git rebase --onto <newbase> <upstream>\n\nvs\n\n$ env GIT_EDITOR=true git rebase -i --onto <newbase> <upstream>\n\nBoth in theory produce an identical end-result, while using two\ndifferent implementations.\n\n(Here I'm setting GIT_EDITOR=true just to demonstrate that I didn't\nchange the list of commits in the latter case.)\n\nj.\n"},{"id":"133600","messageId":"alpine.DEB.1.00.1002041414530.4505@intel-tinevez-2-302","threadId":"22515","inReplyTo":"76718491002032019i5f8ea947paa527988ddb7a378@mail.gmail.com","subject":"Re: rebase vs rebase -i","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2010-02-04T13:27:26Z","receivedAt":"2010-02-04T13:27:26Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 3 Feb 2010, Jay Soffian wrote:\n\n> Why does git rebase use format-patch + am, while rebase -i uses \n> cherry-pick?\n\nHysterical raisins. 'rebase -i' started out as 'edit-patch-series.sh', \nhacked together in 4 hours on a lazy Saturday afternoon:\nhttp://colabti.org/irclogger/irclogger_log/git?date=2007-02-27#l97\n\nAh, the old days. Back when I had enough time to read through Peff's \nmails. And back when I had enough time to cobble together fun Git scripts.\n\n> Just curious. In particular though, it seems especially odd in this \n> case:\n> \n> $ git rebase --onto <newbase> <upstream>\n> \n> vs\n> \n> $ env GIT_EDITOR=true git rebase -i --onto <newbase> <upstream>\n> \n> Both in theory produce an identical end-result, while using two\n> different implementations.\n> \n> (Here I'm setting GIT_EDITOR=true just to demonstrate that I didn't\n> change the list of commits in the latter case.)\n\nYou can get _exactly_ the same behavior if you use -m.\n\nCiao,\nDscho\n"},{"id":"133617","messageId":"76718491002040914t12956bb2gbe21ae89f31cbc7f@mail.gmail.com","threadId":"22515","inReplyTo":"alpine.DEB.1.00.1002041414530.4505@intel-tinevez-2-302","subject":"Re: rebase vs rebase -i","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2010-02-04T17:14:24Z","receivedAt":"2010-02-04T17:14:24Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Feb 4, 2010 at 8:27 AM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n>> (Here I'm setting GIT_EDITOR=true just to demonstrate that I didn't\n>> change the list of commits in the latter case.)\n>\n> You can get _exactly_ the same behavior if you use -m.\n\nOr rather, -p. ;-)\n\nj.\n"},{"id":"133628","messageId":"alpine.DEB.1.00.1002041859000.4505@intel-tinevez-2-302","threadId":"22515","inReplyTo":"76718491002040914t12956bb2gbe21ae89f31cbc7f@mail.gmail.com","subject":"Re: rebase vs rebase -i","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2010-02-04T18:00:04Z","receivedAt":"2010-02-04T18:00:04Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 4 Feb 2010, Jay Soffian wrote:\n\n> On Thu, Feb 4, 2010 at 8:27 AM, Johannes Schindelin\n> <Johannes.Schindelin@gmx.de> wrote:\n> >> (Here I'm setting GIT_EDITOR=true just to demonstrate that I didn't\n> >> change the list of commits in the latter case.)\n> >\n> > You can get _exactly_ the same behavior if you use -m.\n> \n> Or rather, -p. ;-)\n\nNo.  -p tries to preserve merges, and it will use \ngit-rebase--interactive.sh for hysterical raisins.\n\nI meant -m.\n\nCiao,\nDscho\n"},{"id":"133630","messageId":"76718491002041010k84ad55ct5c3e80529e8f8428@mail.gmail.com","threadId":"22515","inReplyTo":"alpine.DEB.1.00.1002041859000.4505@intel-tinevez-2-302","subject":"Re: rebase vs rebase -i","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2010-02-04T18:10:58Z","receivedAt":"2010-02-04T18:10:58Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Feb 4, 2010 at 1:00 PM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Thu, 4 Feb 2010, Jay Soffian wrote:\n>\n>> On Thu, Feb 4, 2010 at 8:27 AM, Johannes Schindelin\n>> <Johannes.Schindelin@gmx.de> wrote:\n>> >> (Here I'm setting GIT_EDITOR=true just to demonstrate that I didn't\n>> >> change the list of commits in the latter case.)\n>> >\n>> > You can get _exactly_ the same behavior if you use -m.\n>>\n>> Or rather, -p. ;-)\n>\n> No.  -p tries to preserve merges, and it will use\n> git-rebase--interactive.sh for hysterical raisins.\n>\n> I meant -m.\n\nI don't understand what you mean by \"_exactly_ the same behavior\" then.\n\n\"GIT_EDITOR=true git rebase -i\" and \"git rebase -p\" both use\ngit-rebase--interactive.sh, and so are exactly the same behavior.\n\n-m still uses git-rebase.sh, but calls merge instead of format-patch +\nam. Perhaps the end-result is the same, but the behavior is different.\n\nI guess I'm being a bit pedantic here, but I'm really just trying to\nunderstand what you mean.\n\nThanks,\n\nj.\n"},{"id":"133631","messageId":"alpine.DEB.1.00.1002041946170.4505@intel-tinevez-2-302","threadId":"22515","inReplyTo":"76718491002041010k84ad55ct5c3e80529e8f8428@mail.gmail.com","subject":"Re: rebase vs rebase -i","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2010-02-04T18:46:42Z","receivedAt":"2010-02-04T18:46:42Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 4 Feb 2010, Jay Soffian wrote:\n\n> On Thu, Feb 4, 2010 at 1:00 PM, Johannes Schindelin\n> <Johannes.Schindelin@gmx.de> wrote:\n>\n> > On Thu, 4 Feb 2010, Jay Soffian wrote:\n> >\n> >> On Thu, Feb 4, 2010 at 8:27 AM, Johannes Schindelin\n> >> <Johannes.Schindelin@gmx.de> wrote:\n> >> >> (Here I'm setting GIT_EDITOR=true just to demonstrate that I didn't\n> >> >> change the list of commits in the latter case.)\n> >> >\n> >> > You can get _exactly_ the same behavior if you use -m.\n> >>\n> >> Or rather, -p. ;-)\n> >\n> > No.  -p tries to preserve merges, and it will use\n> > git-rebase--interactive.sh for hysterical raisins.\n> >\n> > I meant -m.\n> \n> I don't understand what you mean by \"_exactly_ the same behavior\" then.\n\nBoth \"rebase -i\" and \"rebase -m\" are really a cherry-pick in a loop.\n\nCiao,\nDscho"},{"id":"133635","messageId":"76718491002041157o37de139brb7995076274375aa@mail.gmail.com","threadId":"22515","inReplyTo":"alpine.DEB.1.00.1002041946170.4505@intel-tinevez-2-302","subject":"Re: rebase vs rebase -i","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2010-02-04T19:57:13Z","receivedAt":"2010-02-04T19:57:13Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Feb 4, 2010 at 1:46 PM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> Both \"rebase -i\" and \"rebase -m\" are really a cherry-pick in a loop.\n\nWell then I'm still confused. I see where pick_one() in\ngit-rebase--interactive.sh is using cherry-pick.\n\nBut call_merge() in git-rebase.sh is using git-merge-recursive (absent\nspecifying another strategy).\n\n?\n\nj.\n"},{"id":"133651","messageId":"7vmxzose72.fsf@alter.siamese.dyndns.org","threadId":"22515","inReplyTo":"76718491002041157o37de139brb7995076274375aa@mail.gmail.com","subject":"Re: rebase vs rebase -i","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-02-05T00:45:21Z","receivedAt":"2010-02-05T00:45:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> On Thu, Feb 4, 2010 at 1:46 PM, Johannes Schindelin\n> <Johannes.Schindelin@gmx.de> wrote:\n>> Both \"rebase -i\" and \"rebase -m\" are really a cherry-pick in a loop.\n>\n> Well then I'm still confused. I see where pick_one() in\n> git-rebase--interactive.sh is using cherry-pick.\n>\n> But call_merge() in git-rebase.sh is using git-merge-recursive (absent\n> specifying another strategy).\n>\n> ?\n\nI think Dscho's point is that cherry-pick internally runs the same\nmerge-recursive.\n\nWhen you have a change C based on its parent C^ and want to replay that\neffect on a (possibly unrelated) commit A, you would run three-way merge,\nmerging C into A as if C^ is the common ancestor.  The rebase script\ncherry-pick, and revert all work with the same principle (for revert\nobviously you would swap C and C^---you are applying the effect of going\nfrom C to C^ in that case).\n\nAnd no, \"format-patch --stdout | am -3\" pipe in the normal rebase codepath\nwill stay unless you can produce a benchmark that says the performance of\nmerge machinery is good enough these days.  Back when \"rebase -m\" was\nintroduced, it wasn't.\n"},{"id":"133653","messageId":"7vy6j8pjj8.fsf@alter.siamese.dyndns.org","threadId":"22515","inReplyTo":"7vmxzose72.fsf@alter.siamese.dyndns.org","subject":"Re: rebase vs rebase -i","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-02-05T01:18:19Z","receivedAt":"2010-02-05T01:18:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> And no, \"format-patch --stdout | am -3\" pipe in the normal rebase codepath\n> will stay unless you can produce a benchmark that says the performance of\n> merge machinery is good enough these days.  Back when \"rebase -m\" was\n> introduced, it wasn't.\n\nJust for fun, I pulled from the kernel tree.  Its tip is at fc76be4 (Merge\nmaster.kernel.org:/home/rmk/linux-2.6-arm, 2010-02-04), which is a merge\nof a subsystem tree into the mainline.\n\nI tried to rebase HEAD^2 (i.e. subsystem change) on top of HEAD^1 (the\nstate Linus merged that subsystem change into).  Either way, the\nexperiment is to linearlize a side branch that has 16 patches:\n\nThe experiment is to take a history of this shape:\n\n  --A-...--N--O--P master^2 = test (subsystem tip)\n                  \\\n             ---X--Y master\n          master^1\n\nand turn it into a history of this shape:\n\n\n  --A-...--N--O--P master^2 = test (subsystem tip)\n                  \\\n             ---X--Y master\n                 \\\n                  A'-B'-...O'-P' (rebased tip)\n\nThe tree at rebased tip P' must match the merge Y, of course.\n\nFirst, to prepare:\n\n    $ git checkout -b test master^2 ;# at the tip of subsystem\n    $ git checkout HEAD^0 ;# detach so that I can easily repeat\n\nBest of 5 runs on my box are:\n\n    $ git reset --hard test && time git rebase master^1\n    real    0m3.060s\n    user    0m1.976s\n    sys     0m0.812s\n\nvs\n\n    $ git reset --hard test && time git -m rebase master^1\n    real    0m19.060s\n    user    0m15.025s\n    sys     0m3.564s\n\nThe numbers are understandable; the series touches only 12 paths among\n31.5k paths, so applying patches has to be faster.\n\nI have a plan to make a merge go faster by using a yet another merge\nstrategy, but that has been backburnered for now.\n"},{"id":"133654","messageId":"76718491002041720y104c0778s8614fea5e9038905@mail.gmail.com","threadId":"22515","inReplyTo":"7vmxzose72.fsf@alter.siamese.dyndns.org","subject":"Re: rebase vs rebase -i","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2010-02-05T01:20:53Z","receivedAt":"2010-02-05T01:20:53Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Feb 4, 2010 at 7:45 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> I think Dscho's point is that cherry-pick internally runs the same\n> merge-recursive.\n\nAh hah, that's what I was missing. Thank you.\n\n> When you have a change C based on its parent C^ and want to replay that\n> effect on a (possibly unrelated) commit A, you would run three-way merge,\n> merging C into A as if C^ is the common ancestor.  The rebase script\n> cherry-pick, and revert all work with the same principle (for revert\n> obviously you would swap C and C^---you are applying the effect of going\n> from C to C^ in that case).\n>\n> And no, \"format-patch --stdout | am -3\" pipe in the normal rebase codepath\n> will stay unless you can produce a benchmark that says the performance of\n> merge machinery is good enough these days.  Back when \"rebase -m\" was\n> introduced, it wasn't.\n\nIndeed, the difference is painful on a largish tree (910M after gc\n--aggressive, 39k files). Best of 3 runs for each of these:\n\n$ time git rebase --onto HEAD~11 HEAD~10\nFirst, rewinding head to replay your work on top of it...\n[...]\nreal\t0m11.164s\nuser\t0m2.671s\nsys\t0m4.836s\n\n$ time git rebase -m --onto HEAD~11 HEAD~10\n[...]\nreal\t0m40.507s\nuser\t0m17.848s\nsys\t0m16.052s\n\n$ time GIT_EDITOR=\"sed -i -e 1d\" git rebase -i HEAD~11\n[...]\nreal\t0m27.758s\nuser\t0m12.615s\nsys\t0m13.134s\n\nIt looks like there's room for improvement to rebase -m. (2.53 Ghz\nCore 2 Duo Macbook Pro, 4GB memory.)\n\nj.\n"}]}