{"thread":{"id":"6041","subject":"Updated Kernel Hacker's guide to git","startedAt":"2006-12-21T03:04:17Z","lastAt":"2006-12-22T08:50:32Z","messageCount":14,"participants":["Jeff Garzik","Willy Tarreau","Nigel Cunningham","Jay Cliburn","Martin Langhoff","Junio C Hamano","Linus Torvalds","Francois Romieu","Guennadi Liakhovetski","Jesper Juhl"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"29893","messageId":"4589F9B1.2020405@garzik.org","threadId":"6041","inReplyTo":null,"subject":"Updated Kernel Hacker's guide to git","fromName":"Jeff Garzik","fromEmail":"jeff@garzik.org","sentAt":"2006-12-21T03:04:17Z","receivedAt":"2006-12-21T03:04:17Z","isPatch":false,"sender":{"key":"jeff@garzik.org","avatar":null},"body":"I refreshed my git intro/cookbook for kernel hackers, at \nhttp://linux.yyz.us/git-howto.html\n\nThis describes most of the commands I use in day-to-day kernel hacking. \n  Let me know if there are glaring errors or missing key commands.\n\n\tJeff\n"},{"id":"29902","messageId":"4589FD9E.2010000@bellsouth.net","threadId":"6041","inReplyTo":"4589F9B1.2020405@garzik.org","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Jay Cliburn","fromEmail":"jacliburn@bellsouth.net","sentAt":"2006-12-21T03:21:02Z","receivedAt":"2006-12-21T03:21:02Z","isPatch":false,"sender":{"key":"jacliburn@bellsouth.net","avatar":null},"body":"Jeff Garzik wrote:\n> I refreshed my git intro/cookbook for kernel hackers, at \n> http://linux.yyz.us/git-howto.html\n> \n> This describes most of the commands I use in day-to-day kernel hacking. \n>  Let me know if there are glaring errors or missing key commands.\n\nThanks for doing this.  I've referred to your previous page rather often \nas I grope around trying to learn git and hack a vendor driver for \nsubmittal into the mainline kernel.\n\nOne thing that baffled me was how to use git to create a \"kitchen sink\" \ndiff that would produce my entire driver suitable for submittal to lkml \nfor review.  This probably isn't needed very often, but for new driver \nsubmittals it's important to know how to do it.  Francois Romieu showed \nme how (assume the new driver branch is named \"driver\"):\n\n$ git diff $(git merge-base master driver)..driver\n\nAs a beginner, this command continues to be utterly non-intuitive to me, \nbut it works.  There may be other ways to do it, too.\n\nThe point is, I think you should add instructions on your cookbook that \naddress how to produce such a \"kitchen sink\" diff if you're submitting a \nbrand new driver to lkml.  (Obviously I don't know what such a diff is \nactually called.)\n\nJay\n"},{"id":"29898","messageId":"20061221054445.GL24090@1wt.eu","threadId":"6041","inReplyTo":"4589F9B1.2020405@garzik.org","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Willy Tarreau","fromEmail":"w@1wt.eu","sentAt":"2006-12-21T05:44:45Z","receivedAt":"2006-12-21T05:44:45Z","isPatch":false,"sender":{"key":"w@1wt.eu","avatar":"https://avatars.githubusercontent.com/u/8141789?v=4"},"body":"Hi Jeff !\n\nOn Wed, Dec 20, 2006 at 10:04:17PM -0500, Jeff Garzik wrote:\n> I refreshed my git intro/cookbook for kernel hackers, at \n> http://linux.yyz.us/git-howto.html\n\nThanks for this update, it was my most useful source of inspiration\nwhen I started with git.\n\n> This describes most of the commands I use in day-to-day kernel hacking. \n>  Let me know if there are glaring errors or missing key commands.\n\nI very often use \"git-format-patch -k -m\" to produce individual patches\nthat I delay, merge in other branches, or even in other trees with\n\"git-am -k -3\".  I believe it was Davem who suggested this a while ago,\nand I agree it's very convenient to maintain a patch collection (and\nsometimes to clean them up).\n\nAlso, I think that for beginners, you have not insisted enough on the\nfact that they should not modify the master branch, but that they\nshould immediately create their own branch before any local changes.\n\nI got caught by this when I started, and had trouble playing with the\norigin branch to try to fix my mistakes.\n\nOverall it's a good tutorial anyway.\n\nCheers,\nWilly\n"},{"id":"29899","messageId":"1166680407.3636.25.camel@nigel.suspend2.net","threadId":"6041","inReplyTo":"4589F9B1.2020405@garzik.org","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Nigel Cunningham","fromEmail":"nigel@nigel.suspend2.net","sentAt":"2006-12-21T05:53:27Z","receivedAt":"2006-12-21T05:53:27Z","isPatch":false,"sender":{"key":"nigel@nigel.suspend2.net","avatar":null},"body":"Hi.\n\nOn Wed, 2006-12-20 at 22:04 -0500, Jeff Garzik wrote:\n> I refreshed my git intro/cookbook for kernel hackers, at \n> http://linux.yyz.us/git-howto.html\n> \n> This describes most of the commands I use in day-to-day kernel hacking. \n>   Let me know if there are glaring errors or missing key commands.\n\nThanks for the work! I'd suggest also saying how to repack and cleanup.\nCould also be a good idea to go through the steps for uploading to\nmaster.kernel.org or elsewhere?\n\nRegards,\n\nNigel\n"},{"id":"29903","messageId":"46a038f90612202304uabdffacld857cfcb90ec3e76@mail.gmail.com","threadId":"6041","inReplyTo":"4589FD9E.2010000@bellsouth.net","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2006-12-21T07:04:27Z","receivedAt":"2006-12-21T07:04:27Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On 12/21/06, Jay Cliburn <jacliburn@bellsouth.net> wrote:\n> $ git diff $(git merge-base master driver)..driver\n\nThere is a nicer way to do it with 1.4.x git -- note the 3 dots:\n\n$ git diff master...driver\n\ncheers,\n\n\nmartin\n"},{"id":"29904","messageId":"7vk60l1z7u.fsf@assigned-by-dhcp.cox.net","threadId":"6041","inReplyTo":"46a038f90612202304uabdffacld857cfcb90ec3e76@mail.gmail.com","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-21T07:32:05Z","receivedAt":"2006-12-21T07:32:05Z","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> On 12/21/06, Jay Cliburn <jacliburn@bellsouth.net> wrote:\n>> $ git diff $(git merge-base master driver)..driver\n>\n> There is a nicer way to do it with 1.4.x git -- note the 3 dots:\n>\n> $ git diff master...driver\n\nCareful.\n\nI think Jay was looking at this kind of ancestry graph:\n\n         *---*---*---* driver\n        /\n --o---o---x---x---x---x master\n\nThere might be quite a few merges on either side, but the point\nis '*' are not yet 'in', and 'o' and 'x' are already in the\n'upstream (but 'x' are not in Jay's driver yet).\n\nThe three dots would give both '*' and 'x'; I do not think that\nis what Jay wants.  A submitter to mainline usually wants only\n'*' commits.\n\nI've always thought that 'submission' is supposed to be done as\na series of patches, in which case a reasonable way would be to\ndo:\n\n\tgit format-patch -n master driver\n\nIf on the other hand a single roll-up patch is desired, I think\nthe most reasonable thing to do is to first merge the tip of the\nmaster to the tip of driver, resolve all the conflicts as\nneeded, and take the diff between the 'master' and the result:\n\n\n         *---*---*---*---y driver (y is the test merge)\n        /               / \n --o---o---x---x---x---x master\n\n\tgit checkout driver\n        git merge master\n\t... resolve conflicts if any, then \"git commit\"\n\tgit diff master\n\nThis diff by definition should apply cleanly to the tip of\n'master' and would result in the source that contains the\nupdates for the driver.\n\nWhen you are done, it would be advisable to do:\n\n\tgit reset --hard HEAD^\n\nto remove that 'y' merge, unless the merge involved a true\nconflict resolution.\n"},{"id":"29906","messageId":"Pine.LNX.4.64.0612202317110.3576@woody.osdl.org","threadId":"6041","inReplyTo":"4589FD9E.2010000@bellsouth.net","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-12-21T07:51:20Z","receivedAt":"2006-12-21T07:51:20Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 20 Dec 2006, Jay Cliburn wrote:\n> \n> $ git diff $(git merge-base master driver)..driver\n\nBe careful. This ONLY works if you don't have criss-cross merges etc, so \nyou need to be somewhat careful about it. If you end up having a complex \nmerge history between the origin branch and your development tree, things \nwill stop working\n\nSo it's actually worth understanding what the above does.\n\nHere's the picture to keep in mind: you started off with something like \nthis:\n\n\t<- older\t\t\tnewer ->\n\n\t..--A---B---C---D\n\nwhere the top commit was D, and you started doing your own work off there. \nHowever, the tree you are tracking (doing \"git fetch origin\" or somethng) \nALSO continues, so soon enough you'll have a history that looks like\n\n\t<- older\t\t\tnewer ->\n\n\t..--A---B---C---D---E---F---G---H <-\"origin\"\n\t                 \\\n\t                  --X---Y---Z <- your \"driver\" branch\"\n\nwhere your work is the \"X-Y-Z\" sequence.\n\nHow, the reason you must NOT do\n\n\tgit diff origin..driver\n\nor something like that, is that it will LITERALLY do a diff between those \ntwo heads. And while that is a perfectly normal diff, it's not what you \nwant: it's the diff between the up-stream work and yours, and it will show \nthat a lot of work has _not_ happened in your branch (all the E-F-G-H \nstuff), and then you've added some work (X-Y-Z).\n\nWhat you obviously WANT to have is the \"diff\" between \"D\" (which was the \npoint where you started) and \"Z\" (which is where you are now. That's what \nyou want to send up-stream.\n\nNow, the way people used to do this under CVS, was to simply _remember_ D. \nPreferably by doing a tag at the point where they started working. Then \nyou can always diff against that tag.\n\nYou can do that in git too, of course, but it would just be stupid. \nBecause git actually _knows_ the history, so you can just ask git\n\n\t\"What is the most recent commit that both 'origin' and 'driver'\n\t have in common?\"\n\nthe answer, of course, is the very commit you want: D. And how do you ask \nfor that \"most recent common commit\"? That's right: it's called the \"merge \nbase\", because it's also the thing you'd use as the base in a bog-standard \nthree-way merge.\n\nSo \"git merge-base origin driver\" just returns \"D\", without you having had \nto tag it or remember it at all.\n\nSo when you do\n\n\tgit diff $(git merge-base origin driver)..driver\n\nyou're literally asking for the diff between your current top of the \n\"driver\" branch, and the place where you diverged from \"origin\".\n\nNow, why do I mention the fact that THIS DOES NOT WORK if you do merges \nand you no longer have a linear tree? Think about it. If you actually ever \npull on the up-stream and create a merge in your development tree, the \ncommit history graph will now look something like this:\n\n\t<- older\t\t\tnewer ->\n\n\t..--A---B---C---D---E---F---G---H <-\"origin\"\n\t                 \\        \\\n\t                  --X---Y--M--Z <- your \"driver\" branch\"\n\nwhere the \"M\" commit is because you merged some new work from origin.\n\nBut see what that did to the most recent commit? Now, the most recent \ncommit is no longer \"D\". In fact, it's not even your \"merge\" commit, if \nyou think about it (even though you might naively think so), because that \nmerge commit doesn't even exist in \"origin\", so clearly it cannot be the \nmost recent common commit.\n\nThe most recent commit in common is \"F\". So now,\n\n\tgit diff $(git merge-base origin driver)..driver\n\nwill give the difference between _F_ and your current tip Z.\n\nThe thing is, THIS IS STILL THE RIGHT THING TO DO. It's magic. Since you \ndid a merge in M, all the things up until F have been merged into Z too, \nso you actually NO LONGER want to diff against D. Nor do you want to diff \nagainst M (since that would mean that you would not see the work you did \nin X and Y). \n\nBy doing a diff against F (and your own merge having done the right \nthing), you actually end up getting the \"union\" of work for X-Y-Z when you \ndo that magic command line.  If you had done it against D, you'd have seen \nthe work in E and F that the merge M brought in - but you don't want that, \nbecause you want just the work YOU did, not anything in \"origin\".\n\nSo what you want is actually exactly again the most recent common commit.\n\nHOWEVER. While it magically \"just works\" in things like this, it doesn't \nactually work for the really complex cases. If I've merged an eariler \nversion of your work AND you did a merge from me too, you can have a \ncriss-cross merge where there simply isn't one \"most recent common commit\" \nat all any more, but two or more. And then you really do need to do more.\n\nThis is one reason why I suggest developers not merge from me very often: \nif your development tree is just a straight line (ie you only had that one \nmerge), you can't ever even get in that situation, and perhaps as \nimportantly, if/when I pull from you, the result will also tend to look \nmore understandable to people who look at the history.\n\nBut another way to avoid a criss-cross merge is actually to never let me \nsee your tree at all, and then you can merge with me as often as you damn \nwell like. And in that case, the magic\n\n\tgit diff $(git merge-base origin driver)..driver\n\nis always going to give you exactly what you want. You can use merges to \nkeep up-to-date, and always see what you want to send off by email \nupstream. The history will look like crap (you'll end up having a ton of \nmerges in your tree), but if you aren't going to publicise your history \nanyway (just the diff end result), why would you care?\n\n(And yes, you can actually do \"git diff origin...driver\" with _three_ \ndots. I'm not even going to explain _why_ that works, because that's a \nwhole other kettle of fish, and is actually a magic special case in \nbuiltin-diff.c. So feel free to use it because it's short and sweet, but \nthe long format is actually easier to explain what it actually MEANS).\n\n\t\tLinus\n"},{"id":"29939","messageId":"458A73A6.4010805@garzik.org","threadId":"6041","inReplyTo":"1166680407.3636.25.camel@nigel.suspend2.net","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Jeff Garzik","fromEmail":"jeff@garzik.org","sentAt":"2006-12-21T11:44:38Z","receivedAt":"2006-12-21T11:44:38Z","isPatch":false,"sender":{"key":"jeff@garzik.org","avatar":null},"body":"Nigel Cunningham wrote:\n> Hi.\n> \n> On Wed, 2006-12-20 at 22:04 -0500, Jeff Garzik wrote:\n>> I refreshed my git intro/cookbook for kernel hackers, at \n>> http://linux.yyz.us/git-howto.html\n>>\n>> This describes most of the commands I use in day-to-day kernel hacking. \n>>   Let me know if there are glaring errors or missing key commands.\n> \n> Thanks for the work! I'd suggest also saying how to repack and cleanup.\n\nYes, I should mention repacking.  When you say cleanup, what \nspecifically do you mean?\n\n\n> Could also be a good idea to go through the steps for uploading to\n> master.kernel.org or elsewhere?\n\nYes, push should be mentioned at the very least.\n\n\tJeff\n"},{"id":"29941","messageId":"458A75B2.6050201@garzik.org","threadId":"6041","inReplyTo":"4589FD9E.2010000@bellsouth.net","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Jeff Garzik","fromEmail":"jeff@garzik.org","sentAt":"2006-12-21T11:53:22Z","receivedAt":"2006-12-21T11:53:22Z","isPatch":false,"sender":{"key":"jeff@garzik.org","avatar":null},"body":"Jay Cliburn wrote:\n> Jeff Garzik wrote:\n>> I refreshed my git intro/cookbook for kernel hackers, at \n>> http://linux.yyz.us/git-howto.html\n>>\n>> This describes most of the commands I use in day-to-day kernel \n>> hacking.  Let me know if there are glaring errors or missing key \n>> commands.\n> \n> Thanks for doing this.  I've referred to your previous page rather often \n> as I grope around trying to learn git and hack a vendor driver for \n> submittal into the mainline kernel.\n> \n> One thing that baffled me was how to use git to create a \"kitchen sink\" \n> diff that would produce my entire driver suitable for submittal to lkml \n> for review.  This probably isn't needed very often, but for new driver \n> submittals it's important to know how to do it.  Francois Romieu showed \n> me how (assume the new driver branch is named \"driver\"):\n> \n> $ git diff $(git merge-base master driver)..driver\n> \n> As a beginner, this command continues to be utterly non-intuitive to me, \n> but it works.  There may be other ways to do it, too.\n> \n> The point is, I think you should add instructions on your cookbook that \n> address how to produce such a \"kitchen sink\" diff if you're submitting a \n> brand new driver to lkml.  (Obviously I don't know what such a diff is \n> actually called.)\n\nYou inflict upon yourself all sorts of pain if you keep updating \n'master', but don't merge that into 'driver'.  Typically you want to \nrebase after updating master:\n\n\tgit checkout driver\n\tgit rebase master\n\t# build and test\n\tgit prune\n\nor merge master into your current branch:\n\n\tgit checkout driver\n\tgit pull . master\n\t# build and test\n\nThat way, you are GUARANTEED that\n\n\tgit diff master..driver\n\nwill result in a diff that you can send upstream.\n\nOne moral of this story, as (I think) Linus mentioned, don't update \n'master' too frequently.  That's one key lesson of distributed \nprogramming.  Unless the upstream kernel has a key API change or bug fix \nyou need, just pretend the outside world does not exist, and hack away \non your driver.\n\n\tJeff\n"},{"id":"29949","messageId":"20061221135349.GB25184@electric-eye.fr.zoreil.com","threadId":"6041","inReplyTo":"4589F9B1.2020405@garzik.org","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Francois Romieu","fromEmail":"romieu@fr.zoreil.com","sentAt":"2006-12-21T13:53:49Z","receivedAt":"2006-12-21T13:53:49Z","isPatch":false,"sender":{"key":"romieu@fr.zoreil.com","avatar":null},"body":"Jeff Garzik <jeff@garzik.org> :\n> I refreshed my git intro/cookbook for kernel hackers, at \n> http://linux.yyz.us/git-howto.html\n> \n> This describes most of the commands I use in day-to-day kernel hacking. \n>  Let me know if there are glaring errors or missing key commands.\n\no 'git whatchanged shnortz' can probably be replaced with\n  'git log -- schnortz' so there is one command less to remember.\n\no \"Display changes since last git-update-index:\"\n  Fine but you have not told the reader what git-update-index is.\n\n-- \nUeimor\n"},{"id":"29968","messageId":"Pine.LNX.4.60.0612212135230.5551@poirot.grange","threadId":"6041","inReplyTo":"4589F9B1.2020405@garzik.org","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Guennadi Liakhovetski","fromEmail":"g.liakhovetski@gmx.de","sentAt":"2006-12-21T20:40:05Z","receivedAt":"2006-12-21T20:40:05Z","isPatch":false,"sender":{"key":"g.liakhovetski@gmx.de","avatar":null},"body":"On Wed, 20 Dec 2006, Jeff Garzik wrote:\n\n> I refreshed my git intro/cookbook for kernel hackers, at\n> http://linux.yyz.us/git-howto.html\n\nVery nice, thanks! A couple of remarks from an absolute git newbie:\n\n1. I heard \"git am\" is supposed to supersede apply-mbox\n\n2. What I often have problems with is - what to do if git spits at me a \nbunch of conflict messages after a seemingly safe pull or similar. Don't \nknow if you want to cover those points but \"git troubleshooting\" would \ndefinitely be a valuable document.\n\nThanks\nGuennadi\n---\nGuennadi Liakhovetski\n"},{"id":"29969","messageId":"458AF2AC.4080304@garzik.org","threadId":"6041","inReplyTo":"Pine.LNX.4.60.0612212135230.5551@poirot.grange","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Jeff Garzik","fromEmail":"jeff@garzik.org","sentAt":"2006-12-21T20:46:36Z","receivedAt":"2006-12-21T20:46:36Z","isPatch":false,"sender":{"key":"jeff@garzik.org","avatar":null},"body":"Guennadi Liakhovetski wrote:\n> On Wed, 20 Dec 2006, Jeff Garzik wrote:\n> \n>> I refreshed my git intro/cookbook for kernel hackers, at\n>> http://linux.yyz.us/git-howto.html\n> \n> Very nice, thanks! A couple of remarks from an absolute git newbie:\n> \n> 1. I heard \"git am\" is supposed to supersede apply-mbox\n\nHey, that's pretty neat.  Glad you told me, this should improve my \nworkflow a bit.\n\n\n> 2. What I often have problems with is - what to do if git spits at me a \n> bunch of conflict messages after a seemingly safe pull or similar. Don't \n> know if you want to cover those points but \"git troubleshooting\" would \n> definitely be a valuable document.\n\nAgreed.\n\n\tJeff\n"},{"id":"29971","messageId":"1166735878.5906.3.camel@nigel.suspend2.net","threadId":"6041","inReplyTo":"458A73A6.4010805@garzik.org","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Nigel Cunningham","fromEmail":"nigel@nigel.suspend2.net","sentAt":"2006-12-21T21:17:58Z","receivedAt":"2006-12-21T21:17:58Z","isPatch":false,"sender":{"key":"nigel@nigel.suspend2.net","avatar":null},"body":"Hi.\n\nOn Thu, 2006-12-21 at 06:44 -0500, Jeff Garzik wrote:\n> Nigel Cunningham wrote:\n> > Hi.\n> > \n> > On Wed, 2006-12-20 at 22:04 -0500, Jeff Garzik wrote:\n> >> I refreshed my git intro/cookbook for kernel hackers, at \n> >> http://linux.yyz.us/git-howto.html\n> >>\n> >> This describes most of the commands I use in day-to-day kernel hacking. \n> >>   Let me know if there are glaring errors or missing key commands.\n> > \n> > Thanks for the work! I'd suggest also saying how to repack and cleanup.\n> \n> Yes, I should mention repacking.  When you say cleanup, what \n> specifically do you mean?\n\nOh, I was just thinking of the related commands - prune-packed,\ncount-objects, fsck-objects and so on. (I know repack does prune-packed\nwhen you use -d, but it might be handy to mention it anyway... or\nnot :>)\n\n> > Could also be a good idea to go through the steps for uploading to\n> > master.kernel.org or elsewhere?\n> \n> Yes, push should be mentioned at the very least.\n\nNigel\n"},{"id":"30033","messageId":"9a8748490612220050t294d3785r94f0b3c74e935b24@mail.gmail.com","threadId":"6041","inReplyTo":"4589F9B1.2020405@garzik.org","subject":"Re: Updated Kernel Hacker's guide to git","fromName":"Jesper Juhl","fromEmail":"jesper.juhl@gmail.com","sentAt":"2006-12-22T08:50:32Z","receivedAt":"2006-12-22T08:50:32Z","isPatch":false,"sender":{"key":"jesper.juhl@gmail.com","avatar":null},"body":"On 21/12/06, Jeff Garzik <jeff@garzik.org> wrote:\n> I refreshed my git intro/cookbook for kernel hackers, at\n> http://linux.yyz.us/git-howto.html\n>\n> This describes most of the commands I use in day-to-day kernel hacking.\n>   Let me know if there are glaring errors or missing key commands.\n>\nVery nice.\n\nA bit on how to revert a commit and how to rebase a branch would make\nit even nicer :)\n\nThank you for a very good document, Jeff.\n\n-- \nJesper Juhl <jesper.juhl@gmail.com>\nDon't top-post  http://www.catb.org/~esr/jargon/html/T/top-post.html\nPlain text mails only, please      http://www.expita.com/nomime.html\n"}]}