{"thread":{"id":"21294","subject":"Git rebase using \"wrong\" commit","startedAt":"2009-10-20T11:26:22Z","lastAt":"2009-10-20T21:20:43Z","messageCount":3,"participants":["Philip Allison","Thomas Rast","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"125471","messageId":"1256037982.7122.31.camel@gridbug.soton.smoothwall.net","threadId":"21294","inReplyTo":null,"subject":"Git rebase using \"wrong\" commit","fromName":"Philip Allison","fromEmail":"philip.allison@smoothwall.net","sentAt":"2009-10-20T11:26:22Z","receivedAt":"2009-10-20T11:26:22Z","isPatch":false,"sender":{"key":"philip.allison@smoothwall.net","avatar":null},"body":"Hello all,\n\tWe have a specific branch (integration/bug-fixes) which is under\ncontinual rebase, shared amongst several developers.  The tracked\ninstances have \"branch.integration/bug-fixes.rebase true\" and\n\"branch.integration/bug-fixes.mergeoptions --no-ff\" - this is working\nwell.  Individual developers merge their topic branches (in this case\nbug fixes) into integration/bug-fixes and push it out.\n\tOccasionally, we want to release some bug fixes, but not others.  IOW,\nwhen integration/bug-fixes comes to be rebased onto master, we wish to\npreserve some of the topic branch merges, but not others.  This usually\nworks fine, but an issue has cropped up where there is a conflict\nbetween two fixes, and only one of the two bug fixes has been released;\nnow, when we come to perform the rebase, it is not working as desired.\n\nOutput of \"git log --first-parent master..integration/bug-fixes\":\n\n-----\ncommit 9f79ca3928d645435d1608e22297dacd2be94e3b\nMerge: 2bc19f9 cd8273f\nAuthor: Philip Allison <philip.allison@smoothwall.net>\nDate:   Tue Oct 20 10:11:06 2009 +0100\n\n    Merge branch 'bug/2' into integration/bug-fixes\n    \n    * bug/2:\n      Unify format of files 1, 2 and 3\n    \n    Conflicts:\n        file1\n\ncommit 2bc19f9af94e03e06fbe5a1034820c606d13c3d3\nMerge: c785da2 b17a93c\nAuthor: Philip Allison <philip.allison@smoothwall.net>\nDate:   Tue Oct 20 10:07:37 2009 +0100\n\n    Merge branch 'bug/1' into integration/bug-fixes\n    \n    * bug/1:\n      Fix file 1\n-----\n\nbug/2 has, effectively, been merged into master; bug/1 has not; hence,\nthere is not (on master) any equivalent change to that which was made to\nresolve the conflict.\n\n\"git rebase -i master\" output (whilst on HEAD of integration/bug-fixes):\n\n-----\npick b17a93c Fix file 1\n\n# Rebase cd8273f..9f79ca3 onto cd8273f\n-----\n\nThe trouble here is that b17a93c is the head of bug/1 - the rebase has\npicked up the changes from that branch and is trying to apply them as a\nfast-forward commit in the newly rebased integration/bug-fixes, instead\nof trying to rebase the *merge* of bug/1 (i.e. 2bc19f9).\n\tThe \"-m\" and \"-p\" options to rebase don't seem to be helping.  I have\ntried getting rebase to \"pick 2bc19f9\" via -i, but that isn't working\neither:\n\n-----\nfatal: Commit 2bc19f9af94e03e06fbe5a1034820c606d13c3d3 is a merge but no\n-m option was given.\nCould not apply 2bc19f9...\n-----\n\nInterestingly, rebase does *not* seem to be trying to recreate 9f79ca3\n(or its second parent), which is the problem I was originally expecting\nto run into.\n\nAt the moment I don't know where to go from here, short of manually\nrecreating the branch as I want it, which I am loathe to do.  Ideas and\nsuggestions much appreciated.\n\nPlease find attached a working copy of the repository, just before any\nattempted rebase.\n\nRegards\n-- \nPhilip Allison\nSenior Developer\n\nSmoothWall Ltd\n1 John Charles Way\nLeeds LS12 6QA\nUnited Kingdom\n\n1 800 959 3760     (USA, Canada and North America)\n0870 1 999 500     (United Kingdom)\n+44 870 1 999 500  (All other countries)\n\nSmoothWall is registered in England: 4298247\n\nThis email and any attachments transmitted with it are confidential\nto the intended recipient(s) and may not be communicated to any\nother person or published by any means without the permission of\nSmoothWall Limited.  Any opinions stated in this message are solely\nthose of the author.  See: http://smoothwall.net/company/email.php\nfor the full text of this notice.\n"},{"id":"125475","messageId":"200910201521.05526.trast@student.ethz.ch","threadId":"21294","inReplyTo":"1256037982.7122.31.camel@gridbug.soton.smoothwall.net","subject":"Re: Git rebase using \"wrong\" commit","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2009-10-20T13:21:04Z","receivedAt":"2009-10-20T13:21:04Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Philip Allison wrote:\n> Please find attached a working copy of the repository, just before any\n> attempted rebase.\n[...]\n> bug/2 has, effectively, been merged into master; bug/1 has not; hence,\n> there is not (on master) any equivalent change to that which was made to\n> resolve the conflict.\n\nOk, so I gather the (simplified) history looks like\n\n  *------A  (master)\n   \\\\__   \\\n    \\  \\   \\\n     B--M1--M2  (topic)\n\nwhere A and B conflict, so M2 is nontrivial.  B is the *second* parent\nto M1, which I originally thought would affect the 'rebase -p', but it\ndoesn't; see below.  (You're talking about bug/2, but the repository\nshows bug/2 == master, so there are only two branches involved.)\n\n> \tOccasionally, we want to release some bug fixes, but not others.  IOW,\n> when integration/bug-fixes comes to be rebased onto master, we wish to\n> preserve some of the topic branch merges, but not others.  This usually\n> works fine, but an issue has cropped up where there is a conflict\n> between two fixes, and only one of the two bug fixes has been released;\n> now, when we come to perform the rebase, it is not working as desired.\n\nThe inherent difficulty with doing a rebase here is, what about the\nmerges?  By definition, git-rebase needs to somehow \"rebuild\" the\ncommits, as defined by the changes they do, on the new base.\n\nThere are several ways how merges can be rebased, and you tried some:\n\n* Not at all; discard the merges.  The result would be\n\n    *---A  (master)\n         \\\n          \\\n           B'  (topic)\n\n  B' will differ substantially from B because there will be a (rebase)\n  conflict.  This is the normal mode of operation, as you noticed:\n\n> \"git rebase -i master\" output (whilst on HEAD of integration/bug-fixes):\n> \n> -----\n> pick b17a93c Fix file 1\n> \n> # Rebase cd8273f..9f79ca3 onto cd8273f\n> -----\n\n* Attempt to rebuild merges; this is the -p flag.  Assume for a second\n  that you have a different history\n\n    *---A  (master)\n     \\   \n      \\   \n       C---M2  (topic2)\n          /\n         *\n\n  where M2 is a merge with some other branch.  'git rebase -i -p\n  master topic2' will attempt to build\n\n    *---A  (master)\n         \\   \n          \\   \n           C---M2  (topic2)\n              /\n             *\n\n  Going back to your scenario, this means building\n\n  *------A--.  (master)\n   \\      \\  \\\n    \\      \\  \\\n     B-----M1--M2  (topic)\n\n  Now there appears to be some bug with rebase -p, because it insists\n  that there is no work at all to do (the buffer is just 'noop').\n  However, rebase -p is known to be somewhat ill-defined and broken.\n  I think that in this case, what actually happens is that the merge\n  from master to topic confuses the initialisation of $REWRITTEN in\n\n\t# line 668\n\tfor c in $(git merge-base --all $HEAD $UPSTREAM)\n\tdo\n\t\techo $ONTO > \"$REWRITTEN\"/$c || die \"blah\"\n        done\n\n  because suddenly the merge-base is A, meaning that the later test\n\n\t# line 712\n\tfor p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)\n\tdo\n\t\tif test -f \"$REWRITTEN\"/$p -a \\( $p != $ONTO -o $sha1 = $first_after_upstream \\)\n\n  fails for all commits except M2.  So what's *actually* rewritten is\n  M2; but doing so is pointless in rebase's eyes, because it assumes\n  the topic will be based on master eventually, so merging master into\n  it is a no-op.  Hence there is nothing to do.\n\n> \tThe \"-m\" and \"-p\" options to rebase don't seem to be helping. I have\n> tried getting rebase to \"pick 2bc19f9\" via -i, but that isn't working\n> either:\n\n-m means something entirely different, namely that git-rebase should\nuse an (internal) merge instead of format-patch|am, which has some\nadvantages but a big speed disadvantage.  This doesn't matter for\nrebase -i as it never uses format-patch|am.\n\nAs for manually picking merge commits, that fails because you're just\ntrying to fool git-cherry-pick into doing something it can't.\n\n> \tWe have a specific branch (integration/bug-fixes) which is under\n> continual rebase, shared amongst several developers.\n[...]\n> At the moment I don't know where to go from here, short of manually\n> recreating the branch as I want it, which I am loathe to do.\n\nNote that there is no real reason to rebase continually unless you\nwant to kick out flawed topics or old versions of branches.  For\nexample, git.git only rebases 'next' immediately after a release.\nFurthermore, even if you go for the 'pu' model which is rebuilt all\nthe time, you can automate this with a script.  There is one in the\n'todo' branch of git.git, called PU.\n\n(I myself just use a list of topics I want merged, and a simple 'git\nmerge $topic' loop.)\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"125533","messageId":"7vws2plq38.fsf@alter.siamese.dyndns.org","threadId":"21294","inReplyTo":"200910201521.05526.trast@student.ethz.ch","subject":"Re: Git rebase using \"wrong\" commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-10-20T21:20:43Z","receivedAt":"2009-10-20T21:20:43Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> Note that there is no real reason to rebase continually unless you\n> want to kick out flawed topics or old versions of branches.  For\n> example, git.git only rebases 'next' immediately after a release.\n> Furthermore, even if you go for the 'pu' model which is rebuilt all\n> the time, you can automate this with a script.  There is one in the\n> 'todo' branch of git.git, called PU.\n>\n> (I myself just use a list of topics I want merged, and a simple 'git\n> merge $topic' loop.)\n\nI do not use PU nor RB from todo these days, by the way.  I instead\nrebuild my branches with Reintegrate (also from todo).\n"}]}