{"thread":{"id":"3022","subject":"git-bisect is magical","startedAt":"2006-01-09T22:41:18Z","lastAt":"2006-01-12T23:49:00Z","messageCount":14,"participants":["walt","Linus Torvalds","Andreas Ericsson","Junio C Hamano","Sytse Wielinga"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"14366","messageId":"dpuoqf$3rp$1@sea.gmane.org","threadId":"3022","inReplyTo":null,"subject":"git-bisect is magical","fromName":"walt","fromEmail":"wa1ter@myrealbox.com","sentAt":"2006-01-09T22:41:18Z","receivedAt":"2006-01-09T22:41:18Z","isPatch":false,"sender":{"key":"wa1ter@myrealbox.com","avatar":null},"body":"Arthur C. Clarke's Third Law states:  Any sufficiently advanced\ntechnology is indistinguishable from magic.\n\nYou guys have done it -- I can't distinguish git-bisect from\nmagic.  It's wonderful, and thank you!\n\nI used it for the first time this morning to find the commit\nwhich caused some kernel breakage.  I just sent off an email\nto the developer whose commit did the breakage, and it only\ntook me about 45 minutes.  (Now all I need to do is sit back\nand wait for his reply saying 'You're an idiot!')\n\nI have one minor suggestion for howto/isolate-bugs-with-bisect.\nLinus states:\n       git bisect good ORIG_HEAD       <- mark ORIG_HEAD as good (or\n                                           whatever other known-good\n                                           thing you booted last)\n\nWell, in my case, I new the last good kernel was *two* updates ago,\nso ORIG_HEAD wasn't the right thing to use.  I had to guess what\nto type instead of 'ORIG_HEAD'.\n\nWhich leads to one more question:  I have my kernel configured to\nadd the -gxxxxxxxx localversion string to the kernel name.  I took\na wild guess that the xxxxxxxx was the right thing to substitute\nfor 'ORIG_HEAD' and I got lucky.  But what about someone who\ndoesn't know the magic 'xxxxxxxx' to use?  If I didn't know enough\nto keep a week's worth of daily kernel-builds with the 'xxxxxxxx'\nto guide me, would I still be able to do what I did today?\n(For example, if this had been a 'git' bug instead of a kernel bug,\nI don't think I could have figured out how to use git-bisect to find\nthe bug -- could I?)\n\nThanks!\n"},{"id":"14376","messageId":"Pine.LNX.4.64.0601091516460.5588@g5.osdl.org","threadId":"3022","inReplyTo":"dpuoqf$3rp$1@sea.gmane.org","subject":"Re: git-bisect is magical","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-01-09T23:38:20Z","receivedAt":"2006-01-09T23:38:20Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 9 Jan 2006, walt wrote:\n>\n> Arthur C. Clarke's Third Law states:  Any sufficiently advanced\n> technology is indistinguishable from magic.\n> \n> You guys have done it -- I can't distinguish git-bisect from\n> magic.  It's wonderful, and thank you!\n\nHey, I'm pretty damn happy with it myself, if I may say so ;)\n\nIt's the _one_ feature that we really never had with BK, and that git does \nreally really well.\n\n> I have one minor suggestion for howto/isolate-bugs-with-bisect.\n> Linus states:\n>        git bisect good ORIG_HEAD       <- mark ORIG_HEAD as good (or\n>                                            whatever other known-good\n>                                            thing you booted last)\n> \n> Well, in my case, I new the last good kernel was *two* updates ago,\n> so ORIG_HEAD wasn't the right thing to use.  I had to guess what\n> to type instead of 'ORIG_HEAD'.\n\nWell, instead of guessing, you can always do the safe thing, and just try, \nor just going far enough back to be really safe.\n\nThe \"go far back\" case is obviously wasteful, and if you go _too_ far \nback, you'll just spend a long time bisecting, but on the other hand, \na binary search is pretty damned efficient, so even going back _way_ too \nfar usually just results in a couple more bisection attempts.\n\nBut if you're unsure, before marking somethng \"good\", you can just test it \nout first, by doing something like\n\n\tgit checkout -b test <version-to-test-here>\n\nand compiling and testing that one. If it's good, you can just do a simple \n\"git bisect good\" to say that the current state was good..\n\nOh, and in general you don't ever have to name the good/bad ones: the \nexample in Documentation/howto states that you should say\n\n\tgit bisect bad master\n\tgit bisect good ORIG_HEAD\n\nbut the fact is, whenever you leave off the version specifier, it will \njust assume that \"current HEAD\" is it. So quite often, a \"git bisect\" run \nwill start with just a simple\n\n\tgit bisect bad\n\nto mark that the current head is bad (of course, that's 100% equivalent to \nsaying \"git bisect bad master\" if you are on the master branch right \nthen).\n\nAnd if you don't remember what your last good kernel was, but you're sure \nthat the last full release was good, you can just do\n\n\tgit bisect good v2.6.15\n\nand be done with it.\n\n(Of course, right now there's 2075 commits in my git tree after 2.6.15, so \nthat's a fair amount of bisecting.. But let's say that you had known more \nexactly, and been able to start off with just 300 commits - you only have \nto do three \"bisect\" runs to whittle the 2075 commits down to that range \nanyway - so it's not like you are totally screwed even if you don't know \nwhere the good one was).\n\n> Which leads to one more question:  I have my kernel configured to\n> add the -gxxxxxxxx localversion string to the kernel name.\n\nGood man.\n\n>\t\t\t\t\t\t I took\n> a wild guess that the xxxxxxxx was the right thing to substitute\n> for 'ORIG_HEAD' and I got lucky.\n\nYes. I guess we should document what the \"-gxxxxx\" thing means in the \nkernel, and that it's simply the short-hand git name for the top commit \nwhen the kernel was compiled. So you did exactly the right thing.\n\n>\t\t\t  But what about someone who\n> doesn't know the magic 'xxxxxxxx' to use?  If I didn't know enough\n> to keep a week's worth of daily kernel-builds with the 'xxxxxxxx'\n> to guide me, would I still be able to do what I did today?\n\nYes. See above. It certainly takes you more effort, but it's not _hugely_ \nmore effort.\n\n> (For example, if this had been a 'git' bug instead of a kernel bug,\n> I don't think I could have figured out how to use git-bisect to find\n> the bug -- could I?)\n\nWell, if you know how git works internally, it's actually fairly easy to \ndo with any random project. You could, for example, just test whether \ngit-1.0.6 was good first. Or, again, just use a sledge-hammer, and go for \nthe original 1.0.\n\nThe alternative is to just ignore tagged versions altogether, and go by \ndate. For example, you could do something like\n\n\tgit log --since=1.week.ago\n\nand just go to the end (right now, for me, that would be commit 8b32572, \naka \"git-init-db(1): Describe --shared and ..\"). Again, just do\n\n\tgit checkout -b test 8b32572\n\nand try that. If it was good, just mark it good and go from there. The \ntest cycle for git is going to be a lot faster than the test cycle for the \nkernel, so you'll find any bug in no time.\n\n\t\tLinus\n"},{"id":"14377","messageId":"43C2F422.9070209@op5.se","threadId":"3022","inReplyTo":"dpuoqf$3rp$1@sea.gmane.org","subject":"Re: git-bisect is magical","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2006-01-09T23:39:14Z","receivedAt":"2006-01-09T23:39:14Z","isPatch":false,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"walt wrote:\n> \n> I have one minor suggestion for howto/isolate-bugs-with-bisect.\n> Linus states:\n>        git bisect good ORIG_HEAD       <- mark ORIG_HEAD as good (or\n>                                            whatever other known-good\n>                                            thing you booted last)\n> \n> Well, in my case, I new the last good kernel was *two* updates ago,\n> so ORIG_HEAD wasn't the right thing to use.  I had to guess what\n> to type instead of 'ORIG_HEAD'.\n> \n\nIt would be neat if resets could optionally be stored as unannotated \ntags as well as ORIG_HEAD, with a date and time in the tag-name.\n\n\tgit tag reset-$(date '+%F_%H.%M.%S')\n\nworks fine for me, although I expect the quibbling about the date-format \nwill never stop. I'll get going on it tomorrow unless I get some \nseriously vehement requests not to, or someone beats me to it.\n\nIf someone *does* beat me to it, perhaps \"git reset --clean-tags\" should \nbe implemented as well?\n\n\n> Which leads to one more question:  I have my kernel configured to\n> add the -gxxxxxxxx localversion string to the kernel name.  I took\n> a wild guess that the xxxxxxxx was the right thing to substitute\n> for 'ORIG_HEAD' and I got lucky.  But what about someone who\n> doesn't know the magic 'xxxxxxxx' to use? \n\n\nI expect you remember the date and approximate time you built it so the \n--tag option should work fairly well there, I'd say. Otherwise, tagging \nthe build like you do is a very good idea.\n\n\n>If I didn't know enough\n> to keep a week's worth of daily kernel-builds with the 'xxxxxxxx'\n> to guide me, would I still be able to do what I did today?\n> (For example, if this had been a 'git' bug instead of a kernel bug,\n> I don't think I could have figured out how to use git-bisect to find\n> the bug -- could I?)\n> \n\nMost likely not as easily, although it would have been fairly easy to \nmark the most recent tag as a known good build, or Linus' latest tree \nfrom upstream.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"14424","messageId":"dq11c6$g15$1@sea.gmane.org","threadId":"3022","inReplyTo":"Pine.LNX.4.64.0601091516460.5588@g5.osdl.org","subject":"Re: git-bisect is magical","fromName":"walt","fromEmail":"wa1ter@myrealbox.com","sentAt":"2006-01-10T19:19:33Z","receivedAt":"2006-01-10T19:19:33Z","isPatch":false,"sender":{"key":"wa1ter@myrealbox.com","avatar":null},"body":"Linus Torvalds wrote:\n[...]\n> but the fact is, whenever you leave off the version specifier, it will \n> just assume that \"current HEAD\" is it...\n\nI'm still very much struggling with nomenclature, and trying to\ndeduce what is a synonym for what, and which words cannot be used\nsynonymously.\n\nYesterday (while reading the bisect HOWTO) I did a git-revert on the\n'bad' commit, which indeed fixed my bug.  But this caused a problem\nthis morning when I did my daily 'cg-update' for the kernel.\n\nI got a merge conflict (of course) because of yesterday's git-revert.\n\nMy question (I think) is:  exactly what did I change when I did the\ngit-revert?  I notice in retrospect that (in refs/heads) master is\nno longer identical to origin.  I think (but I'm not certain) that\nthe two used to be the same.  (For example, in my 'git' repository\nthe 'master' and 'origin' files are identical.)\n\nDid the git-revert change my local kernel repository permanently?\nDid the merge-conflict prevent today's cg-update from updating my\nlocal repository with your commits from the last 24 hours?  Or is\nthe merge conflict only with my currently checked-out-and-modified\ncopy of the repository?\n\nIs it clear to you why I'm confused? :o)  Most of my muddle is\nbecause I don't know the definitions of some important words, I\nsuspect.\n\nThanks!\n"},{"id":"14427","messageId":"Pine.LNX.4.64.0601101131540.4939@g5.osdl.org","threadId":"3022","inReplyTo":"dq11c6$g15$1@sea.gmane.org","subject":"Re: git-bisect is magical","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-01-10T19:42:50Z","receivedAt":"2006-01-10T19:42:50Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 10 Jan 2006, walt wrote:\n> \n> Yesterday (while reading the bisect HOWTO) I did a git-revert on the\n> 'bad' commit, which indeed fixed my bug.  But this caused a problem\n> this morning when I did my daily 'cg-update' for the kernel.\n> \n> I got a merge conflict (of course) because of yesterday's git-revert.\n\nWell, it's not \"of course\". It might have merged fine, and to some degree \nyou were just unlukcy that it created a conflict with new development), \nbut yes, it will now always be a _merge_ rather than a fast-forward, as \nyour tree was now different from my historical tree.\n\n> My question (I think) is:  exactly what did I change when I did the\n> git-revert?\n\nYou can think of a \"git revert\" as being just a \"apply the reverse of that \none diff, and commit it\". So a \"git revert\" really just add a _new_ \ncommit, it never _removes_ anything.\n\n(That's fundamental: in a distributed system you can't undo history).\n\nNow, strictly speaking \"git revert\" actually does something much smarter \nthan just apply the diff in reverse - which means that it works better if \nother things have changed in that area - but if you think of it as the \n\"commit the diff in reverse\" case, you'll be thinking the right way.\n\n>  I notice in retrospect that (in refs/heads) master is\n> no longer identical to origin.  I think (but I'm not certain) that\n> the two used to be the same.  (For example, in my 'git' repository\n> the 'master' and 'origin' files are identical.)\n\nExactly.\n\nDo a \"git-whatchanged -p\", and you'll see what your \"git revert\" did.\n\n> Did the git-revert change my local kernel repository permanently?\n\nYes.\n\nYou can _undo_ the revert, so it's not permanent in that sense. Just do\n\n\tgit reset --hard origin\n\nand your \"master\" branch will be forced back to the state that \"origin\" \nwas in.\n\n> Did the merge-conflict prevent today's cg-update from updating my\n> local repository with your commits from the last 24 hours?  Or is\n> the merge conflict only with my currently checked-out-and-modified\n> copy of the repository?\n\nI'm not sure. It could be either, you don't tell what the conflict message \nis.\n\nIf the conflict message is\n\n\tEntry 'xyzzy' not uptodate. Cannot merge.\n\nthat means that no merge was even tried, because you had dirty contents in \nyour tree, and the merge simply won't touch it. You need to commit the \ndirty state and let the merge try to auto-merge it, or you need to undo \nit so that your tree is clean.\n\nIf the conflict message is something like\n\n\tCONFLICT (content): merge conflict in xyzzy\n\nthat means that the merge _was_ done, but there was a content conflict \nthat you need to fix up by hand and finish the merge.\n\n> Is it clear to you why I'm confused? :o)  Most of my muddle is\n> because I don't know the definitions of some important words, I\n> suspect.\n\nHey, keep the questions coming. And if something starts making sense, I \nsuspect that Junio would be very happy with additions to the Documentation \nsubdirectory to try to help others... Hint, hint.\n\n\t\tLinus\n"},{"id":"14428","messageId":"Pine.LNX.4.64.0601101143180.4939@g5.osdl.org","threadId":"3022","inReplyTo":"Pine.LNX.4.64.0601101131540.4939@g5.osdl.org","subject":"Re: git-bisect is magical","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-01-10T19:45:23Z","receivedAt":"2006-01-10T19:45:23Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 10 Jan 2006, Linus Torvalds wrote:\n> \n> You can _undo_ the revert, so it's not permanent in that sense. Just do\n> \n> \tgit reset --hard origin\n> \n> and your \"master\" branch will be forced back to the state that \"origin\" \n> was in.\n\nBtw, you can try this (careful - it will also undo any dirty state you \nhave in your working tree), and then do the \"pull\" again (which should now \nbe a trivial fast-forward) and then just try to do the \"git revert\" on the \nnew state.\n\nAn even better option is obviously to figure out _why_ that commit broke \nfor you in the first place, and get it fixed up-stream, so that you don't \neven need to revert it any more, and the \"pull\" just fixes it for you ;)\n\n\t\t\tLinus\n"},{"id":"14440","messageId":"dq168p$3kt$1@sea.gmane.org","threadId":"3022","inReplyTo":"Pine.LNX.4.64.0601101143180.4939@g5.osdl.org","subject":"Re: git-bisect is magical","fromName":"walt","fromEmail":"wa1ter@myrealbox.com","sentAt":"2006-01-10T20:43:05Z","receivedAt":"2006-01-10T20:43:05Z","isPatch":false,"sender":{"key":"wa1ter@myrealbox.com","avatar":null},"body":"Linus Torvalds wrote:\n> \n> On Tue, 10 Jan 2006, Linus Torvalds wrote:\n>> You can _undo_ the revert, so it's not permanent in that sense. Just do\n>>\n>> \tgit reset --hard origin\n>>\n>> and your \"master\" branch will be forced back to the state that \"origin\" \n>> was in.\n> \n> Btw, you can try this (careful - it will also undo any dirty state you \n> have in your working tree), and then do the \"pull\" again (which should now \n> be a trivial fast-forward) and then just try to do the \"git revert\" on the \n> new state.\n\nJust by stumbling around and trying things at random, I did a\n'git-checkout origin' which *seemed* to resolve the merge-conflict,\nbut left me feeling uneasy because I don't really understand what\nI'm doing.  Can you give a short explanation of the difference\nbetween 'git reset --hard origin' and 'git-checkout origin'?\n\n> An even better option is obviously to figure out _why_ that commit broke \n> for you in the first place, and get it fixed up-stream...\n\nI'm still waiting for the insulting email from the developer ;o)  How\nlong should I wait for a response before I start bugging other people?\n"},{"id":"14444","messageId":"Pine.LNX.4.64.0601101308540.4939@g5.osdl.org","threadId":"3022","inReplyTo":"dq168p$3kt$1@sea.gmane.org","subject":"Re: git-bisect is magical","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-01-10T21:17:29Z","receivedAt":"2006-01-10T21:17:29Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 10 Jan 2006, walt wrote:\n> \n> Just by stumbling around and trying things at random, I did a\n> 'git-checkout origin' which *seemed* to resolve the merge-conflict,\n> but left me feeling uneasy because I don't really understand what\n> I'm doing.  Can you give a short explanation of the difference\n> between 'git reset --hard origin' and 'git-checkout origin'?\n\n\"git checkout\" actually checks out a different branch (unless, to confuse \nthings, you ask it to just check out a specific _file_, in which case it \nstays on the same branch).\n\nSo when you say \"git checkout origin\", it actually _switches_ to the \norigin branch (which is just my state) and checks that out.\n\nWhen you then do a \"git pull\", you'll just be pulling my newer state into \nthat older content branch, and it will resolve beautifully as a \nfast-forward with no merge at all.\n\nThe downside with being in the \"origin\" branch is that if you now do any \nkind of real development, you've now made \"origin\" mean something else \nthan it traditionally means - now it's no longer a branch tracking the \norigin of your code, now it's an active development branch.\n\nDo \"git checkout master\" to go back to where you used to be.\n\nIn contrast, a \"git reset --hard origin\" would have reset your _current_ \nbranch to the state that the \"origin\" branch was in (and forced a checkout \nof that exact state too - that's what the \"--hard\" flag means).\n\nSo when you say \"git checkout origin\", you should read it as \"check out \nthe origin branch\", and thus it makes perfect sense that \"origin\" now \nbecomes your current branch. In contrast, when you say \"git reset --hard \norigin\", you should mentally read that as \"reset the state of my current \ntree to the same state as the origin branch\".\n\nThe naming does make sense, but you just have to get used to what \n\"checkout\" means (in its two different guises - checking out a file being \ndifferent from checking out a full tree) and what \"reset\" means.\n\n> > An even better option is obviously to figure out _why_ that commit broke \n> > for you in the first place, and get it fixed up-stream...\n> \n> I'm still waiting for the insulting email from the developer ;o)  How\n> long should I wait for a response before I start bugging other people?\n\nHey, send out the report to linux-kernel, and if it is a serious problem, \njust cc me and Andrew (and whoever else seems to be most relevant for the \narea: networking goes to David Miller, drivers mostly to Greg or Jeff etc \netc). Regardless, you should always cc at least the people who signed off \non the commit, since they want to know that they signed off on something \nthat turned out to be buggy.\n\n\t\tLinus\n"},{"id":"14458","messageId":"dq1o88$1bm$1@sea.gmane.org","threadId":"3022","inReplyTo":"Pine.LNX.4.64.0601101308540.4939@g5.osdl.org","subject":"Re: git-bisect is magical","fromName":"walt","fromEmail":"wa1ter@myrealbox.com","sentAt":"2006-01-11T01:50:00Z","receivedAt":"2006-01-11T01:50:00Z","isPatch":false,"sender":{"key":"wa1ter@myrealbox.com","avatar":null},"body":"Linus Torvalds wrote:\n[...]\n> So when you say \"git checkout origin\", it actually _switches_ to the\n> origin branch (which is just my state) and checks that out.\n\nI think we are finally homing in on the very roots of my ignorance!\n\nWhen you use the word 'switches' my eyes go glassy, just like when\nmy wife starts telling me everything I've done wrong today...\n\nPlease --> what am I switching *from* when I switch to 'origin'?\n(Think:  this guy is a total dumbshit!  How can I possibly dumb-\ndown this basic knowledge any dumber?)\n\nI know this is really bone-head-basic-stuff, but I'm quite sure\nthat this lies at the heart of my confusion.\n\nWhen I finally understand this kindergarten material I can graduate\nto first grade  :o)\n\nThanks for your patience!\n"},{"id":"14462","messageId":"7vhd8b1nw7.fsf@assigned-by-dhcp.cox.net","threadId":"3022","inReplyTo":"dq1o88$1bm$1@sea.gmane.org","subject":"Re: git-bisect is magical","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-01-11T02:47:36Z","receivedAt":"2006-01-11T02:47:36Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"walt <wa1ter@myrealbox.com> writes:\n\n> Linus Torvalds wrote:\n> [...]\n>> So when you say \"git checkout origin\", it actually _switches_ to the\n>> origin branch (which is just my state) and checks that out.\n>\n> Please --> what am I switching *from* when I switch to 'origin'?\n\nShort version: if you have only two branches \"master\" and\n\"origin\", then obviously there is only one \"the other one\" ;-).\n\nLonger version:\n\nAt the very beginning, you started your repository like this:\n\n        $ git clone git://git.kernel.org/some/where mine\n        $ cd mine\n\nYou can say:\n\n\t$ git branch\n\nAnd you would see:\n\n\t$ git branch\n        * master\n          origin\n\nSo you have two branches, and you are on \"master\" right now.\n\nYour working tree files are associated with one branch at any\nmoment, and \"git branch\" shows you which branch you are on.\nThat branch is \"the current branch\".  When you make your\ncommits, you will commit into that branch.  The commit-producing\ncommands include \"git commit\", \"git am\", \"git pull\", \"git\nmerge\", \"git revert\" and \"git cherry-pick\".  They all create a\nnew commit on your \"current branch\".  The difference among them\nis where the commit you create takes the modifications from\n(commit from the index file and the working tree, am from a\nmailbox, pull and merge from a different branch, and revert and\ncherry-pick from an existing commit).\n\nYou usually work in your \"master\" branch.  But you do not have\nto.  Suppose you are working on maintaining some product, and\nyou have a couple of trivial bugfixes you can make and one\nrather involved enhancement.  What you could do is to have more\nthan one branches, and use \"master\" for what are ready to be\nconsumed by other people, and another branch for your\ndevelopments.\n\nYour repository at one point might look like this:\n\n        $ git show-branch\n        *  [master] trivial fix #2\n         ! [devel] work in progress #3\n        --\n         + [devel] work in progress #3\n         + [devel^] work in progress #2\n         + [devel~2] work in progress #1\n        +  [master] trivial fix #2\n        +  [master^] trivial fix #1\n        ++ [master~2] released frotz gadget\n\nYou are on the \"master\" branch, and committed two trivial fixes\non top of it since your last release.  But in the meantime you\nfound time to do independent enhancements, not yet finished but\nslowly progressing.  You hope to be able to complete the\ndevelopment and include that in the master branch eventually,\nbut not yet.\n\nHow you would end up to something like above would go like this:\n\n 1. You have just released frotz gadget.  Your \"master\" branch\n    is at that commit, and you do not have the \"devel\" branch\n    yet.\n\n 2. You are inspired by somebody to enhance frotz in a novel\n    way.  You start hacking and accumulate some changes in the\n    working tree files, but now you realize it will be a bigger\n    task than you initially thought.  In the meantime, you got a\n    couple of bug reports and you think you know how to fix them\n    trivially.  But unfortunately, your working tree files are\n    currently in a great mess.  Then:\n\n        $ git checkout -b devel\n\n    This creates a new branch (\"devel\") based on the current\n    branch head (remember, you were on \"master\" branch), and\n    switches to that new branch.  It is a short-hand for the two\n    command sequence:\n\n\t$ git branch devel\n        $ git checkout devel\n\n    This takes your working tree changes with you, so at this\n    point if you do \"git diff\", you will see your changes.  You\n    commit this mess (do not worry about \"presentable history\"\n    yet; you will be cleaning up the mess later anyway before\n    you merge).\n\n\t$ git add new-files-you-created\n\t$ git commit -a -m 'work in progress #1'\n\n 3. Now you can switch mood and can work on the trivial fixes.\n    Go back to the \"master\" branch:\n\n\t$ git checkout master\n\n    you'll notice that all the mess you made while working on\n    devel has been cleaned up --- WIP edits are gone, and if you\n    made new files for \"devel\" they are gone too.  You start\n    from the state immediately after release, and work on fixes,\n    and commit:\n\n\t$ edit for trivial fix number 1\n\t$ git commit -a -m 'trivial fix #1'\n\t$ edit for trivial fix number 2\n\t$ git commit -a -m 'trivial fix #2'\n\n 4. Now fixes are out of your way, you can go back to work on\n    the enhancements.  The same thing as step 3.\n\n\t$ git checkout devel\n\t$ edit / test / commit\n\nEventually what you do in your devel branch comes to maturity\nand ready for public consumption.  How would you make sure when?\nFor that, you would create a throw-away test branch and try\nthings out:\n\n\t$ git branch -f test master\n        $ git checkout test\n        $ git merge 'development trial' test devel\n\nThis would create something like this:\n\n        $ git show-branch\n        !   [master] trivial fix #2\n         !  [devel] work in progress #3\n          * [test] development trial\n        ---\n\t  + [test] development trial\n         ++ [devel] work in progress #3\n         ++ [devel^] work in progress #2\n         ++ [devel~2] work in progress #1\n        + + [master] trivial fix #2\n        + + [master^] trivial fix #1\n        +++ [master~2] released frotz gadget\n\nYou merged \"devel\" and \"master\" in \"test\" branch, so that you\ncan test your development along with the other fixes you had in\nthe \"master\" branch since your \"devel\" branch forked.  Try\nthings out and if you find the result satisfactory, then you\nknow what you have in \"devel\" is good for public consumption.\n\nThere are three ways to bring the \"devel\" into \"master\" at this\nmoment.  It depends on how much you care about clean history.\n\n A) just merge.\n\n\t$ git checkout master\n        $ git pull . devel\n\n    This is the simplest, but you would see all the real history\n    in \"devel\" branch, things like \"work in progress #n\" commit\n    log messages.\n\n B) refactor and linearize.\n\n\t$ git format-patch -k -m -o ./+redo master..devel\n\n    This leaves a patchfile per commit in devel branch in +redo/\n    directory.  You can edit the commit log message and patch\n    just as if you are preparing them for e-mail submission to\n    another project maintainer.  Once you are done editing:\n\n\t$ git checkout master\n        $ git am -k -3 ./+redo/0*.txt\n\n    to apply them on top of the master branch.\n\n C) linearize without refactoring.\n\n\t$ git checkout devel\n        $ git rebase master\n        $ git checkout master\n        $ git pull . devel\n\n    This \"rebases\" the development branch (the first two steps),\n    and then pulls the result into the \"master\" branch (the\n    rest).  It should give you the same result as approach B) if\n    you do not edit your +redo/ files at all.\n\nOnce you are done, you can clean up by\n\n\t$ git branch -D test devel\n"},{"id":"14463","messageId":"Pine.LNX.4.64.0601101846170.3294@g5.osdl.org","threadId":"3022","inReplyTo":"dq1o88$1bm$1@sea.gmane.org","subject":"Re: git-bisect is magical","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-01-11T02:58:56Z","receivedAt":"2006-01-11T02:58:56Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 10 Jan 2006, walt wrote:\n>\n> Linus Torvalds wrote:\n> [...]\n> > So when you say \"git checkout origin\", it actually _switches_ to the\n> > origin branch (which is just my state) and checks that out.\n> \n> I think we are finally homing in on the very roots of my ignorance!\n> \n> When you use the word 'switches' my eyes go glassy, just like when\n> my wife starts telling me everything I've done wrong today...\n\nAhhah.\n\n> Please --> what am I switching *from* when I switch to 'origin'?\n> (Think:  this guy is a total dumbshit!  How can I possibly dumb-\n> down this basic knowledge any dumber?)\n\nOk, this clearly isn't described well enough in any docs, so let me try, \nand hopefully somebody (hint hint) will go \"Ahh, I wish that had been \ndescribed in xyz - here's a patch to do so\".\n\nAnyway, the notion of multiple \"branches\" aka \"heads of development\" is \npretty ingrained in git. It's really how _everything_ subtle gets done \n(merging, you name it - sometimes the branch may be a temporary unnamed \nhead that is just inside a script, but the _concept_ is always there).\n\nThere's one _special_ branch, which is the \"active\" one. The only git \ntrees without an active branch are the so-called \"bare\" git trees, which \nare the .git directory contents directly, without any checked-out state. \nThose are only used for distribution - no development can ever happen in \nthem, because they simply don't have any active branch to do development \n_in_.\n\nBut for any normal git repository, you'll have one active branch, which is \nthe one that your working directory actually represents. It's also the one \nwe call \"HEAD\", since the HEAD thing is the thing that points to the \nactive branch.\n\nYour HEAD can point to _any_ branch, but the default one is called \n\"master\". That's the branch you get when you clone another repository, or \nwhen you just start a new git repository from scratch with \"git-init-db\".\n\nBut you can \"switch\" between branches at any time by just doing a simple \n\"git checkout <branchname>\". That will conceptually totally blow away your \nworking directory contents (well, all of it that git knows about, anyway), \nand replace them with the contents that the _other_ branch contains. Now, \nI say \"conceptually\", because in practice this is heavily optimized, so \nthat any files that don't change aren't actually re-written, so you can \nswitch between two branches that are similar quite cheaply.\n\nSo when you did \"git checkout origin\", you basically blew away all the \ndevelopment you had done in the default \"master\" branch, and switched to \n_another_ branch. The \"origin\" branch is the one that is generated for you \nautomatically when you clone a repository from somewhere else: it \ninitially contains the state of that other repository at the time of the \nclone, and a \"git pull origin\" will actually both \"fetch\" that branch (so \nthat the \"origin\" branch is kept up-to-date with the original source) \n_and_ merge that branch into your HEAD (normally \"master\").\n\n> I know this is really bone-head-basic-stuff, but I'm quite sure\n> that this lies at the heart of my confusion.\n> \n> When I finally understand this kindergarten material I can graduate\n> to first grade  :o)\n\nWell, at least _some_ of this is described in Documentation/git-pull.txt \nand Documentation/tutorial.txt. So if you haven't looked into those \nbefore, try them now. And if you have, they clearly need more effort.\n\nI'm really bad at documentation. I'm more than happy trying to answer \nemailed questions (at least if I get the feeling that the person asking \nthe questions is really trying to learn, which you've done admirably), but \nthat doesn't mean that I'm good at writing the docs. So I'm hoping that \nsome of this can find itself into a FAQ or one of the existing docs, \nthanks to somebody else editing it..\n\n\t\tLinus\n"},{"id":"14480","messageId":"dq3hgn$maf$1@sea.gmane.org","threadId":"3022","inReplyTo":"Pine.LNX.4.64.0601101846170.3294@g5.osdl.org","subject":"Re: git-bisect is magical","fromName":"walt","fromEmail":"wa1ter@myrealbox.com","sentAt":"2006-01-11T18:07:19Z","receivedAt":"2006-01-11T18:07:19Z","isPatch":false,"sender":{"key":"wa1ter@myrealbox.com","avatar":null},"body":"Linus Torvalds wrote:\n[...]\n> So when you did \"git checkout origin\", you basically blew away all the \n> development you had done in the default \"master\" branch, and switched to \n> _another_ branch...\n\nFirst, many thanks to you, Junio, and Sean (by email) for the great\nreplies -- all three were extremely helpful, and this is all finally\nstarting to make sense to me.\n\nNow, I don't know whether this anecdote will give you any new\ninformation, but I'll offer it.\n\nAfter I did the 'git checkout origin' yesterday, I didn't (yet) know\nwhat I was doing, so I made the following pilot-errors while still\nin 'origin':  I did 'git-reset --hard origin' and then very early\nthis morning I did cg-update, both of which seemed to work fine and\ngave no error messages, and I compiled a new kernel from the result.\n\nAfter reading the three essays from you guys :o) I realized that I\nhad made these two mistakes, and tried to switch back to master:\n$git-branch\n  bisect\n  master\n* origin\n$git-checkout master\nfatal: Entry 'Documentation/kernel-parameters.txt' would be overwritten\nby merge. Cannot merge.\n\nSo I cloned a fresh copy of your repository and built a new kernel.\nWhat I learned from this was that the new fixes to Makefile and\nsetlocalversion (at a minimum) were not actually applied to the\nchecked-out sources in my 'origin' misadventure.  (I watched the\ncommits being listed by cg-update, so I know the fixes were really\ndownloaded -- but they were not applied to the checked-out sources\nas they normally would be.)\n\nWould these anomalous results be expected -- given the, um, unusual\ncircumstances?\n\nThanks again!\n"},{"id":"14579","messageId":"20060112215946.GA5808@speedy.student.utwente.nl","threadId":"3022","inReplyTo":"dq3hgn$maf$1@sea.gmane.org","subject":"Re: git-bisect is magical","fromName":"Sytse Wielinga","fromEmail":"s.b.wielinga@student.utwente.nl","sentAt":"2006-01-12T21:59:47Z","receivedAt":"2006-01-12T21:59:47Z","isPatch":false,"sender":{"key":"s.b.wielinga@student.utwente.nl","avatar":null},"body":"On Wed, Jan 11, 2006 at 10:07:19AM -0800, walt wrote:\n> [...]\n> After I did the 'git checkout origin' yesterday, I didn't (yet) know\n> what I was doing, so I made the following pilot-errors while still\n> in 'origin':  I did 'git-reset --hard origin' and then very early\n> this morning I did cg-update, both of which seemed to work fine and\n> gave no error messages, and I compiled a new kernel from the result.\n> \n> After reading the three essays from you guys :o) I realized that I\n> had made these two mistakes, and tried to switch back to master:\n> $git-branch\n>   bisect\n>   master\n> * origin\n> $git-checkout master\n> fatal: Entry 'Documentation/kernel-parameters.txt' would be overwritten\n> by merge. Cannot merge.\n> \n> So I cloned a fresh copy of your repository and built a new kernel.\n\nFunny thing about git is, at least in my experience, that you generally never\nreally have to do this. Because objects are immutable, and basically the only\nthing git -really- cares about is objects, you can always tell git to just\nignore anything you've done (or that anybody else has done, for that matter).\nJust point it to an object somebody else made and it won't see any of your\nlocal changes. If you're not satisfied with the way a branch worked out, just\nremove it, or point it to another object.\n\nBy the way, you can always just move away a broken origin; git-fetch (or\ngit-pull of course, because it uses git-fetch), will just create a new one. If\ngit-branch shows that you currently have origin checked out, do\n\n    # Create a new branch named 'bad-bad-origin' based on HEAD (which equals\n    # origin at the moment) and check it out\n    git-checkout -b bad-bad-origin\n\notherwise do (because it is faster, as it doesn't touch your index file or\nyour working tree)\n\n    # Create a new branch named 'bad-bad-origin' based on origin\n    git-branch bad-bad-origin origin\n\n... and finally remove the old origin:\n\n    git-branch -d origin\n\nAfter this, a git-fetch will just recreate origin, and unlike git-pull does\nnothing that could give you more headbreaks again, so that fixes your broken\norigin. Then optionally backup your master by saying\n\n    git-branch old-master master\n\nand get yourself a nice and clean repository again by typing:\n\n    git-checkout master\n    # Reset the current HEAD (namely, master) to origin\n    git-reset --hard origin\n\nBefore executing any git command that will check out a different tree, though,\nyou will want to make sure you know what you have done to your working tree and\nwhat git will do to your edits when you execute that command. git-diff*,\ngit-ls-files, and git-status are your friends. If either git-ls-files -m or\ngit-ls-files -u (or the combination git-ls-files -m -u, naturally) shows any\nfiles, git will refuse to switch branches if it has to touch any of these\nfiles.\n\nIf you're sure you don't want these changes anymore, you can undo any changes\nwith 'git-reset --hard'. If you wish to save these changes however, you can\neither take the classic approach of saving a diff with git-diff HEAD (just a\nplain git-diff won't do for files in git-ls-files -u, that is, files that you\nalready ran git-update-index on) or you can make a commit and save it in a\ntemporary branch.\n\nFor example, you can make a commit before or after the 'git-checkout -b\nbad-bad-origin' in the beginning of this mail, and the diff will be in\nbad-bad-origin for your later reference by using git-diff-tree -p\nbad-bad-origin.\n\n\nBy the way, if you really don't know what to do anymore, there always is the\nlast resort of fixing things up manually. I'm not recommending you to go this\nway, but it has helped me out a couple of times before I knew all the basic\ncommands, so it seems good to at least mention how you do it.\n\nAll branches are in .git/refs/heads/, so you can just go there and move master\nand origin or any other branch that you like to another name, or remove them,\nor overwrite them with references you pick from other files in .git/refs/heads/\nor git log. Just make sure all they contain is a full sha1-hash, so no names,\njust the hash. And that .git/HEAD is a symlink pointing to one of the files in\nrefs/heads/.\n\nThe drawback, and the reason you should generally not do this unless you don't\nknow any better way to do what you want, is that you can leave the index file\nand the working tree in a state that doesn't correspond to the current HEAD\nanymore. To be sure, you can always go back to the top directory and do a\n'git-reset --hard', and then a 'git-ls-files -z -o |xargs -0 rm --'. This will\nremove any extra files that you have in your working tree, mind you, so make\nsure you move those you still need out of the working tree before doing this.\n\n> What I learned from this was that the new fixes to Makefile and\n> setlocalversion (at a minimum) were not actually applied to the\n> checked-out sources in my 'origin' misadventure.  (I watched the\n> commits being listed by cg-update, so I know the fixes were really\n> downloaded -- but they were not applied to the checked-out sources\n> as they normally would be.)\n>\n> Would these anomalous results be expected -- given the, um, unusual\n> circumstances?\n\nYes. If git tries a merge, but fails, it will leave the results in the working\ntree for you to fix, so that you can finish the merge. If you don't wish to\nfinish the merge, just do a git-reset --hard and your tree is clean again.\n\n> Thanks again!\n\nNo thank _you_, for explaining so well what exactly you didn't understand! :-)\n\n        Sytse Wielinga\n"},{"id":"14582","messageId":"dq6ptd$ft8$1@sea.gmane.org","threadId":"3022","inReplyTo":"20060112215946.GA5808@speedy.student.utwente.nl","subject":"Re: git-bisect is magical","fromName":"walt","fromEmail":"wa1ter@myrealbox.com","sentAt":"2006-01-12T23:49:00Z","receivedAt":"2006-01-12T23:49:00Z","isPatch":false,"sender":{"key":"wa1ter@myrealbox.com","avatar":null},"body":"Sytse Wielinga wrote:\n[...]\n> No thank _you_, for explaining so well what exactly you didn't understand! :-)\n\nI am totally blown away by the amount of useful information in your\npost!  I have scanned through what you sent, but I will need some time\nto digest it all.\n\nI promise you that I *will* understand every word of what you wrote,\neven if I have to ignore my wife for a week!  (Maybe longer ;o)\n\nThank you!  I foresee a great future for you in private industry.\n(I say that because the ability to write clearly is not very much\nvalued in government or academia...)\n"}]}