{"thread":{"id":"3089","subject":"git rebase behaviour changed?","startedAt":"2006-01-17T03:49:50Z","lastAt":"2006-01-17T08:56:21Z","messageCount":9,"participants":["Mike McCormack","Junio C Hamano","Martin Langhoff"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"14760","messageId":"43CC695E.2020506@codeweavers.com","threadId":"3089","inReplyTo":null,"subject":"git rebase behaviour changed?","fromName":"Mike McCormack","fromEmail":"mike@codeweavers.com","sentAt":"2006-01-17T03:49:50Z","receivedAt":"2006-01-17T03:49:50Z","isPatch":false,"sender":{"key":"mike@codeweavers.com","avatar":null},"body":"\nHi,\n\ngit-rebase was a very useful tool for me to help organize my patches.\n\nRecently, it seems the behaviour of git-rebase changed.  It used to take \nthe commits I'd made to my \"master\" branch and reapply them to a new \n\"master\" branch on top of \"origin\".  Where rebase from git-0.99.x used \nto work, git-1.1.3 now does nothing and gives me the following message:\n\ngit-rebase origin\n-> Current branch refs/heads/master is up to date.\n\nHowever, I can do the \"rebase\" manually with:\n\ngit branch master-20060117\ngit reset --hard origin\ngit-format-patch -k --stdout --full-index origin master-20060117 | \\\n\tgit am --binary -3 -k\n\nIs this broken, or am I meant to be doing something different now?\n\nthanks,\n\nMike\n"},{"id":"14763","messageId":"7vslrnh080.fsf@assigned-by-dhcp.cox.net","threadId":"3089","inReplyTo":"43CC695E.2020506@codeweavers.com","subject":"Re: git rebase behaviour changed?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-01-17T05:50:23Z","receivedAt":"2006-01-17T05:50:23Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Mike McCormack <mike@codeweavers.com> writes:\n\n> git-rebase origin\n> -> Current branch refs/heads/master is up to date.\n>\n> However, I can do the \"rebase\" manually with:\n>\n> git branch master-20060117\n> git reset --hard origin\n> git-format-patch -k --stdout --full-index origin master-20060117 | \\\n> \tgit am --binary -3 -k\n>\n> Is this broken, or am I meant to be doing something different now?\n\nWhat does \"git-merge-base master-20060117 origin\" give you?  If\nit is the same as \"origin\", then the master-20060117 has been\nmerged with origin, and rebase does not run in this case.\n\nHere is the simplest example:\n\n                  1---2---3---4 master\n                 /\n        origin  0\n\nOf course, you _could_ extract patches #1, #2, #3, and #4\nbetween origin and master, and apply them on top of #0 to\nreconstruct \"master\" as you found out, but there is not much\npoint doing so.\n\nRebase changes the \"master\" branch when the development track\nbetween you (master) and upstream (origin) have forked:\n\n                  1---2---3---4 master\n                 /\n        origin' 0---5---6 origin\n\nIn this case, things are rearranged by rebase:\n\n                        1'--2'--3'--4' master\n                       /\n        origin' 0--5--6 origin\n\n\nEnd of on-topic answers.\n\n\nBTW, what this means is that it would not rearrange something\nlike this:\n\n                    2---3\n                   /     \\\n                  1---4---5---6 master\n                 / \n        origin  0\n\nBut a structure like this could be rebased:\n\n                    2---3\n                   /     \\\n                  1---4---5---6 master\n                 / \n        origin' 0---7---8 origin\n\nto produce something like this:\n\n                          1'--2'--3'--4'--6' master\n                         / \n        origin' 0---7---8 origin\n\nThe ordering of patches may turn out to be wrong; #4 might\nconflict with already applied #2 and #3.  In general, rebasing\nsuch a merged structure is highly discouraged.  I think there\nwas a discussion on this topic on the list recently, and a short\nsummary was: \"if you do a merge, do not rebase; if you are going\nto rebase, do not merge\".  The thread is this one:\n\n\thttp://thread.gmane.org/gmane.comp.version-control.git/14308\n\nEspecially please look at a couple of message from Linus:\n\n\thttp://article.gmane.org/gmane.linux.kernel/365410\n        http://article.gmane.org/gmane.linux.kernel/365409\n        http://article.gmane.org/gmane.linux.kernel/365501\n\nI guess we could decompose the commit ancestry chain in such a\ncase, and reproduce something like this:\n\n                            2'--3'\n                           /     \\\n                          1'--4'--5'--6' master\n                         / \n        origin' 0---7---8 origin\n\nRebase has never done this, though.  It is left as an exercise\nfor the reader ;-).\n"},{"id":"14766","messageId":"43CC89DC.5060201@codeweavers.com","threadId":"3089","inReplyTo":"7vslrnh080.fsf@assigned-by-dhcp.cox.net","subject":"Re: git rebase behaviour changed?","fromName":"Mike McCormack","fromEmail":"mike@codeweavers.com","sentAt":"2006-01-17T06:08:28Z","receivedAt":"2006-01-17T06:08:28Z","isPatch":false,"sender":{"key":"mike@codeweavers.com","avatar":null},"body":"\nJunio C Hamano wrote:\n\n> Rebase changes the \"master\" branch when the development track\n> between you (master) and upstream (origin) have forked:\n> \n>                   1---2---3---4 master\n>                  /\n>         origin' 0---5---6 origin\n\nWell, I thought I was in the above situation, but it seems that \"origin\" \nhas been merged into \"master\" :/\n\nThe \"pull, rebase, commit, commit, send patches, pull, ...\" strategy \nused to work for me, but now it doesn't.\n\n > summary was: \"if you do a merge, do not rebase; if you are going\n > to rebase, do not merge\".  The thread is this one:\n\nI want to do rebases.  So is it that behaviour of \"git pull\" that has \nbeen changed to do merges, and I should be using \"fetch\" instead of \n\"pull\" or something similar?\n\nMike\n\n\nbtw. I'm not the only person having this problem.  Others using the same \ncommands, and upgrading GIT have run into it too, so something has \nchanged...\n"},{"id":"14768","messageId":"7v7j8zfjv5.fsf@assigned-by-dhcp.cox.net","threadId":"3089","inReplyTo":"43CC89DC.5060201@codeweavers.com","subject":"Re: git rebase behaviour changed?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-01-17T06:29:02Z","receivedAt":"2006-01-17T06:29:02Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Mike McCormack <mike@codeweavers.com> writes:\n\n> btw. I'm not the only person having this problem.  Others using the\n> same commands, and upgrading GIT have run into it too, so something\n> has changed...\n\nSorry, I accidentally removed the part from my message where I\nsaid \"Yes it was changed on Nov 28 after discussion on the list\nregarding rebase\".\n\n\t$ git whatchanged -S'is up to date' git-rebase.sh\n\nwould show that commit.\n"},{"id":"14769","messageId":"46a038f90601162252y7e2d9227p4eb4091b653d5c6d@mail.gmail.com","threadId":"3089","inReplyTo":"43CC89DC.5060201@codeweavers.com","subject":"Re: git rebase behaviour changed?","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2006-01-17T06:52:32Z","receivedAt":"2006-01-17T06:52:32Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On 1/17/06, Mike McCormack <mike@codeweavers.com> wrote:\n>  > summary was: \"if you do a merge, do not rebase; if you are going\n>  > to rebase, do not merge\".  The thread is this one:\n>\n> I want to do rebases.  So is it that behaviour of \"git pull\" that has\n> been changed to do merges, and I should be using \"fetch\" instead of\n> \"pull\" or something similar?\n\nNow, I have realised that a simple mistake (merging from origin in you\nscenario) would lead git-rebase to discard earlier patches during the\nrebase. If you had a single commit *after* the merge, git-rebase would\nhave rebased that single patch, and dropped earlier patches.\n\ngit-rebase should refuse to run in the above scenario. Is there a\nstraightforward way to ask if the merge base is \"shared\"?\n\n<thinking>\nIf the commit following right after the merge base on \"our\" side is a\nmerge commit, there's a good chance we're about to fuck up. To make\ndouble sure, we can walk up that commit to the other parent (the one\nthat is not the merge base for the current merge) and get what merge\nbase between that commit and the current merge base. If it returns\nanything interesting, we bail out if we are conservative -- or walk up\nthe history again if we take a more adventurous approach.\n\nIf it returns empty, it's a splice merge and get outta here -- you are\nnot supposed to rebase a splice merge. And if the merge after our\noriginal merge base was an octopus, die too. Those are not rebasable\neither.\n</thinking>\n\nSo, the conservative (and easy) approach would be to make rebase bail\nout when it finds any merge commit.\n\ncheers,\n\n\nmartin\n"},{"id":"14772","messageId":"7v8xtfclyx.fsf@assigned-by-dhcp.cox.net","threadId":"3089","inReplyTo":"46a038f90601162252y7e2d9227p4eb4091b653d5c6d@mail.gmail.com","subject":"Re: git rebase behaviour changed?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-01-17T08:11:50Z","receivedAt":"2006-01-17T08:11:50Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin Langhoff <martin.langhoff@gmail.com> writes:\n\n> Now, I have realised that a simple mistake (merging from origin in you\n> scenario) would lead git-rebase to discard earlier patches during the\n> rebase. If you had a single commit *after* the merge, git-rebase would\n> have rebased that single patch, and dropped earlier patches.\n\nIt may not necessarily be a mistake.\n\n> git-rebase should refuse to run in the above scenario. Is there a\n> straightforward way to ask if the merge base is \"shared\"?\n>\n> <thinking>\n>...\n> </thinking>\n\nSorry I am always slow but I am a bit slower than I usually am\ntonight, and do not understand this part without an\nillustration:\n\n        master    1---2---3---4---5---A\n                 /           /\n\torigin  0---6---7---B\n\n\n                A = master head\n                B = origin head == merge base\n\n\trev-list B..A = 1 2 3 4 5\n        rev-list A..B = 6 7\n\nThe first rev-list is \"what we have but they do not\".  They are\nthe candidates to be fed upstream.  The latter is \"what they\nhave but we do not\".  Potentially some of them are commit that\nrepresent patches we submitted earlier upstream.\n\nAmong the first list of commit, there is #4 which is a merge.\nSo we reject.  Is that what you meant?  Which makes sense in\nthis picture (but I am a bit tired and maybe this may not apply\nin a different picture).\n\n\nBy the way, the longer I think about this, the more I agree with\nthe conclusion of the earlier thread: \"if you rebase, do not\nmerge; if you merge, do not rebase\".  It is really about picking\nthe right workflow.\n\nLet's say you submitted #1, #2, #3 earlier, and #3 was accepted\nupstream and came back as #7, and let's further assume that we\nare lucky enough that patch-id gives the same answer for\n\"diff-tree #2\" and \"diff-tree #7\".  So the set of commits left\nare #1, #3, and #5 (#4 is just a merge so we will not re-apply).\n\nNow, what is the shape of the final \"rebased\" ancestry graph we\nwould want?\n\n\n        master                1'--3'--5'--A'\n                             /\n\torigin  0---6---7---B\n\nIf this is what we want, why did we make #4 merge in the first\nplace, I wonder.  If the workflow is based on rebase [*1*],\ninstead of making a merge at #4, the developer *should* have\ndone fetch and rebase, not merge:\n\n        master    1---2---3\n                 /\n\torigin  0---6---7---B\n\n        ==>\n\n        master                1'--3'\n                             /\n\torigin  0---6---7---B\n\nThis would have been easier to manage at the point we discovered\n#6, #7, and #B, than creating #4 merge only to discard it later.\n\nAnd #5 and #A can be built on top of #3'.\n\n        master                1'--3'--5---A\n                             /\n\torigin  0---6---7---B\n\n\n[Footnote]\n\n*1* That is certainly easier to manage for an individual\ndeveloper than a merge based workflow.  I know it because I\noperated that way for a long time back when Linus was managing\ngit)\n"},{"id":"14774","messageId":"46a038f90601170033y334d111fjed277fc787a2e523@mail.gmail.com","threadId":"3089","inReplyTo":"7v8xtfclyx.fsf@assigned-by-dhcp.cox.net","subject":"Re: git rebase behaviour changed?","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2006-01-17T08:33:23Z","receivedAt":"2006-01-17T08:33:23Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On 1/17/06, Junio C Hamano <junkio@cox.net> wrote:\n> Sorry I am always slow but I am a bit slower than I usually am\n> tonight, and do not understand this part without an\n> illustration:\n\n\nMy fault. I did have a few bits of paper here on my lap, but gmail's\ntextbox sucks at ascii art...\n\n>\n>         master    1---2---3---4---5---A\n>                  /           /\n>         origin  0---6---7---B\n>\n>\n>                 A = master head\n>                 B = origin head == merge base\n>\n>         rev-list B..A = 1 2 3 4 5\n>         rev-list A..B = 6 7\n\nYep, exacly the example I was thinking about.\n\n(...)\n> Among the first list of commit, there is #4 which is a merge.\n> So we reject.  Is that what you meant?\n\nExactly. We refuse to reset the head and begin the rebase operation,\nbecause it looks like operator error.\n\n> By the way, the longer I think about this, the more I agree with\n> the conclusion of the earlier thread: \"if you rebase, do not\n> merge; if you merge, do not rebase\".  It is really about picking\n> the right workflow.\n\nDefinitely. But errors and misunderstandings are frequent, and people\nwho haven't thought the process through or aren't that familiar with\nthe internals are very likely to try it.\n\nRefusing to rebase, with a good error msg gives the user a chance to\nevaluate what to do with the commits. Right now, if I read the\nsituation right, there's a good chance commits 1,2 and 3 will be\n\"lost\" once the rebase is complete.\n\nGIT won't literally lose them,  someone could run git-fsck and fish\nout the dangling heads from the repo, and after a bit of spelunking\nrecover them, but it's suddenly a really tricky operation.\n\ncheers,\n\n\nmartin\n"},{"id":"14775","messageId":"7vvewjb5xz.fsf@assigned-by-dhcp.cox.net","threadId":"3089","inReplyTo":"46a038f90601170033y334d111fjed277fc787a2e523@mail.gmail.com","subject":"Re: git rebase behaviour changed?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-01-17T08:43:20Z","receivedAt":"2006-01-17T08:43:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin Langhoff <martin.langhoff@gmail.com> writes:\n\n> GIT won't literally lose them,  someone could run git-fsck and fish\n> out the dangling heads from the repo, and after a bit of spelunking\n> recover them, but it's suddenly a really tricky operation.\n\n\"git-lost-found\".\n\nYou are right.  We will lose #1 and #2, (although the \"already\nup to date\" might catch some cases) and this _is_ dangerous.  I\nneed to do something about this soon.\n\nThanks for the discussion.\n\n\n[Footnote]\n\n*1* ... or #1 and #3 --- sorry, my \"one of them picked up by\nupstream\" scenario description was inconsistent in the previous\nmessage.\n"},{"id":"14776","messageId":"7vhd83b5ca.fsf@assigned-by-dhcp.cox.net","threadId":"3089","inReplyTo":"7vvewjb5xz.fsf@assigned-by-dhcp.cox.net","subject":"Re: git rebase behaviour changed?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-01-17T08:56:21Z","receivedAt":"2006-01-17T08:56:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> You are right.  We will lose #1 and #2, (although the \"already\n> up to date\" might catch some cases) and this _is_ dangerous.  I\n> need to do something about this soon.\n\nActually, I think we are OK; I do not think we would lose any\ncommits.  git-format-patch (actually, git-cherry called from\nthere) does the right thing.  It does not use the merge base\ndone in git-rebase in any way.\n\nIn any case, we _do_ need an explanation and error-out upon\nfinding a merge, as we discussed.  If somebody really wants to\nrebase a merge, he can do that by hand, as Mike easily\ndemonstrated.\n"}]}