{"thread":{"id":"21781","subject":"\"git merge\" merges too much!","startedAt":"2009-11-29T03:21:25Z","lastAt":"2009-12-09T19:56:46Z","messageCount":33,"participants":["Greg A. Woods","Jeff King","Junio C Hamano","Dmitry Potapov","Jeff Epler","Nanako Shiraishi","Uri Okrent","Marko Kreen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"128656","messageId":"m1NEaLp-000kn1C@most.weird.com","threadId":"21781","inReplyTo":null,"subject":"\"git merge\" merges too much!","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-11-29T03:21:25Z","receivedAt":"2009-11-29T03:21:25Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"I'm trying to learn to use Git to manage local changes.  I'm very new to\nGit (hi all!), but not new at all to version tracking tools in general.\n\nHope I've found the right list on which to ask potentially naive\nquestions!  I've been doing _lots_ of reading about Git, but I can't\nseem to find anything about the problems I relate below.\n\nOne task I'm working on is to try to find the best way to merge changes\nmade from one branch to another, eg. to propagate local fixes from one\nrelease to another.\n\nHowever in at least one simple case \"git merge\" merges too much.\n\nI have something like this started from a remote-cloned repository where\nBL1.2 is a branch from the remote master HEAD, which happens to\ncorrespond to a tag \"TR1.2\", the release-1.2 tag, and I've made three\nlocal commits to my local BL1.2 branch: A, B, and C:\n\n                                         BL1.2 - A - B - C  <- BL1.2 HEAD\n                                        /\nmaster 1 - 2 - TR1.1 - 3 - 4 - 5 - TR1.2  <- master HEAD\n\n\n(there are no \"release\" branches in this project, just tags on the\nmaster branch to represent release points -- is there any way to get\n\"git log\" to show which tags are associated with a given commit and/or\nbranch?  The real project is freedesktop.org's xinit repo, but the real\ntree is too messy to diagram here -- hopefully I've extracted the\nessence of the problem correctly)\n\nI now want to create a branch \"BL1.1\" and merge commits A, B, and C to it\nin order to back-port my local fixes to the TR1.1 release.  \"TR1.1\" is\nsimply a tag on the origin/master trunk.\n\nI do the following:\n\n\tgit checkout -b BL1.1 TR1.1\n\tgit merge BL1.2\n\nHowever this seems to merge all of 3, 4, and 5, as well as A, B, and C.\n\nI think I can (barely) understand why it's doing what it's doing, but\nthat's not what I want it to do.  However it looks like Git doesn't have\nthe same idea of a branch \"base\" point as I think I do.\n\nRunning \"git log TR1.2..BL1.2\" does show me exactly the changes I wish\nto propagate, but \"git merge TR1.2..BL1.2\" says \"not something we can\nmerge\".  Sigh.\n\nHow can I get it to merge just the changes from the \"base\" of the BL1.2\nbranch to its head?\n\nIs using either git-cherry-pick or \"git log -p | git-am\", the only way\nto do this?  Which way best preserves Git's ability to realize if a\nchange has already been included on the target branch, if any?\n\nIs this the kind of \"problem\" that drove the creators of Stacked-Git to\ninvent their tools?\n\nIs there any way to get \"git log --graph\" (and/or gitk) to show me all\nthe branch heads, not just the current/specified one?\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\n+1 416 218-0098                VE3TCP          RoboHack <woods@robohack.ca>\nPlanix, Inc. <woods@planix.com>      Secrets of the Weird <woods@weird.com>\n"},{"id":"128661","messageId":"20091129051427.GA6104@coredump.intra.peff.net","threadId":"21781","inReplyTo":"m1NEaLp-000kn1C@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-11-29T05:14:27Z","receivedAt":"2009-11-29T05:14:27Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Nov 28, 2009 at 10:21:25PM -0500, Greg A. Woods wrote:\n\n> Hope I've found the right list on which to ask potentially naive\n> questions!  I've been doing _lots_ of reading about Git, but I can't\n> seem to find anything about the problems I relate below.\n\nYep, you're in the right place.\n\n> master branch to represent release points -- is there any way to get\n> \"git log\" to show which tags are associated with a given commit and/or\n\nTry \"git log --decorate\".\n\n>                                          BL1.2 - A - B - C  <- BL1.2 HEAD\n>                                         /\n> master 1 - 2 - TR1.1 - 3 - 4 - 5 - TR1.2  <- master HEAD\n>\n> [...]\n> \n> \tgit checkout -b BL1.1 TR1.1\n> \tgit merge BL1.2\n> \n> However this seems to merge all of 3, 4, and 5, as well as A, B, and C.\n> \n> I think I can (barely) understand why it's doing what it's doing, but\n> that's not what I want it to do.  However it looks like Git doesn't have\n> the same idea of a branch \"base\" point as I think I do.\n\nYes. Git doesn't really view history as branches in the way you are\nthinking. History is simply a directed graph, and when you merge two\nnodes in the graph, it takes into account _everything_ that happened\nto reach those two points since the last time they diverged (which in\nyour case is simply TR1.1, as BL1.2 is a strict superset).\n\nThere is no way in the history graph to represent \"we have these\ncommits, but not this subsequence\". You have to create new commits A',\nB', and C' which introduce more or less the same changes as their\ncounterparts (and they may even be _exactly_ the same except for the\nparentage, but then again, they may not if the changes they make do not\napply in the same way on top of TR1.1).\n\n> Running \"git log TR1.2..BL1.2\" does show me exactly the changes I wish\n> to propagate, but \"git merge TR1.2..BL1.2\" says \"not something we can\n> merge\".  Sigh.\n> \n> How can I get it to merge just the changes from the \"base\" of the BL1.2\n> branch to its head?\n> \n> Is using either git-cherry-pick or \"git log -p | git-am\", the only way\n> to do this?  Which way best preserves Git's ability to realize if a\n> change has already been included on the target branch, if any?\n\nYes, you must cherry-pick or use rebase (which is a more featureful\nversion of the pipeline you mentioned). Either way will produce an\nequivalent set of commits (cherry-pick is useful when you are picking a\ncouple of commits; rebase is useful for rewriting a whole stretch of\nhistory. It sounds like you want to do the latter).\n\nThe resulting commits will have different commit ids, but git generally\ndoes a good job at merging such things, because it looks only at the\nresult state and not the intermediate commits.  If both sides have made\nan equivalent change, then there is no conflict.\n\n> Is there any way to get \"git log --graph\" (and/or gitk) to show me all\n> the branch heads, not just the current/specified one?\n\nTry \"--all\" with either gitk or \"git log\". Or if you want a subset of\nheads, just name them.\n\nHope that helps,\n-Peff\n"},{"id":"128662","messageId":"7vskbxewti.fsf@alter.siamese.dyndns.org","threadId":"21781","inReplyTo":"m1NEaLp-000kn1C@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-11-29T05:15:05Z","receivedAt":"2009-11-29T05:15:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"In order to make things smoother and easier in the future, you may want to\nlearn \"topic branch\" workflows (found in many git tutorial material).\n\nBut it is too late for the history you already created; \"cherry-pick\" is\nyour friend to recover from the shape of your existing history.\n"},{"id":"128794","messageId":"m1NFAji-000kn2C@most.weird.com","threadId":"21781","inReplyTo":"20091129051427.GA6104@coredump.intra.peff.net","subject":"Re: \"git merge\" merges too much!","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-11-30T18:12:31Z","receivedAt":"2009-11-30T18:12:31Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"Thank you very much for confirming my understanding of why \"git merge\"\nwas merging more changes than I had desired it to merge.\n\nThe way \"git merge\" works does concern me somewhat though as I try to\nfigure out how I might use \"topic\" branches to develop local features\nand then merge them onto each supported release branch.  Some guides\nI've read suggest this methodology, but I'm sure how well this will\nwork, even when the remote project uses release branches to manage\nofficial releases.  Perhaps I really should look at StGit, but I'm not\nsure about it either.\n\n\nAt Sun, 29 Nov 2009 00:14:27 -0500, Jeff King <peff@peff.net> wrote:\nSubject: Re: \"git merge\" merges too much!\n> \n> On Sat, Nov 28, 2009 at 10:21:25PM -0500, Greg A. Woods wrote:\n> > \n> > master branch to represent release points -- is there any way to get\n> > \"git log\" to show which tags are associated with a given commit and/or\n> \n> Try \"git log --decorate\".\n\nExcellent!  That's exactly what I was looking for.\n\n(From a first pass through the documentation I would never have guessed\nthat \"tags\" were also a form of \"refs\".  All these different names for\nthings in the Git vs.  many other VCS's, like \"ref names\" _really_\nconfusing to anyone like me with too much experience using those other\nrevision control systems.  Part of the problem is that Git documentation\nseems to be two-or-more minded about several of its concepts and\nfeatures.  Even the gitglossary(7) is somewhat inconsistent on how it\nuses \"ref\" and \"refs\".  Perhaps all that's needed is some firm editing\nand clean-up of the manuals and documentation by a good strong technical\neditor.)\n\n\n> Yes, you must cherry-pick or use rebase (which is a more featureful\n> version of the pipeline you mentioned).\n\n\"git rebase\" will not work for me unless it grows a \"copy\" option ,\ni.e. one which does not delete the original branch (i.e. avoids the\n\"reset\" phase of its operation).  This option would likely only make\nsense when used with the \"--onto\" option, I would guess.\n\n\"git rebase -i\" would certainly give me all the control I could possibly\nwant when copying changes from branch to branch.\n\nIt likely wouldn't make sense to base this new \"copy\" feature directly\non \"git rebase\" though, especially in light of all the warnings about\nhow \"git rebase\" isn't friendly when applied to already published\nbranches.  I think in theory this \"copy\" feature won't cause problems\nfor already-published branches.\n\nPerhaps it should be a whole new top-level command such as \"git copy\",\nbut then it's so much like \"git merge\" I'm not sure....  Ideally if \"git\nmerge\" could be taught how to work with just the changes from the base\nof a branch then it would do what I'm looking for directly.\n\n\n> The resulting commits will have different commit ids, but git generally\n> does a good job at merging such things, because it looks only at the\n> result state and not the intermediate commits.  If both sides have made\n> an equivalent change, then there is no conflict.\n\n> > Is there any way to get \"git log --graph\" (and/or gitk) to show me all\n> > the branch heads, not just the current/specified one?\n> \n> Try \"--all\" with either gitk or \"git log\". Or if you want a subset of\n> heads, just name them.\n\nAwsome!  Those options provide just what I wanted to see!\n\n(git-log(1) is worse than ls(1) for having too many options, but worst\nof all in the release I'm still using it doesn't respond sensibly nor\nconsistently with other commands when given the \"-?\" option.)\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\n+1 416 218-0098                VE3TCP          RoboHack <woods@robohack.ca>\nPlanix, Inc. <woods@planix.com>      Secrets of the Weird <woods@weird.com>\n"},{"id":"128796","messageId":"m1NFBAx-000kmgC@most.weird.com","threadId":"21781","inReplyTo":"7vskbxewti.fsf@alter.siamese.dyndns.org","subject":"Re: \"git merge\" merges too much!","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-11-30T18:40:38Z","receivedAt":"2009-11-30T18:40:38Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Sat, 28 Nov 2009 21:15:05 -0800, Junio C Hamano <gitster@pobox.com> wrote:\nSubject: Re: \"git merge\" merges too much!\n> \n> In order to make things smoother and easier in the future, you may want to\n> learn \"topic branch\" workflows (found in many git tutorial material).\n\nI was thinking hard about topic branches too, but I'm still having a\nhard time figuring out how they might work best for my purposes.\n\nOne hard problem is how to create \"clean\" topic branches and use them\neffectively when the local working environment requires all or many of\nthe whole set of local changes.  Bootstrapping these local changes as\ntopic branches may be one thing; but going further with topic branches\nto create local features or fixes, some of which are to be submitted\nupstream for eventual inclusion in the origin/master branch, and others\nof which will only ever be ported forward to future official releases,\nis quite another thing all together.\n\nThese new-feature topic branches will have to be worked on from the\nmain (most well supported) local branch, which will be forked from the\nmain release branch (or based on the trunk at the main release tag), but\nyet care will have to be taken to make sure the merge doesn't include\ndependencies on local-only changes (i.e. so that it can be safely\nsubmitted upstream).\n\nSome projects also only wish to receive patches that work against their\ntrunk branch, so a given local topic branch will have to be merged onto\nyet another branch forking from the trunk where it may likely encounter\nconflicts (since the topic branch is based on older code from an\nexisting release).  This isn't really a Git problem I suppose, except\nfor the fact that it means the lack of easy support for multiple working\ndirectories that track different branches makes this kind of development\nsomewhat more difficult to do with Git than with, say, CVS.\n\nWhile it may be quite convenient in small projects to quickly move a\nsingle working directory from one branch to another and do various\nbuilds and tests from the result, large projects (say where a compile\ntakes the better part of a working day or more and where testing\nrequires multi-day processes) demand that working directories remain\n\"stable\", and multiple lines of development therefore demand multiple\nworking directories.  Developing procedures around Git to manage this\nwith \"push\" and \"pull\" into multiple local copies of the repository,\neach with their own working directory, is of course possible (though not\nnecessarily easy), but once again if the repositories are similarly huge\nthen it may not be possible to support multiple repo copies for each\ndeveloper in a given working environment.\n\nSo, ideally it seems from my understanding at this point that I want to\nbe able to repeatedly merge topic branch changes (as they are worked on)\ninto multiple local configuration branches (each of which perhaps\nincludes multiple local topics and other changes), each of which pushes\nits changes out into possibly multiple working directories.\n\n\n> But it is too late for the history you already created; \"cherry-pick\" is\n> your friend to recover from the shape of your existing history.\n\nThe problem is that it's not _my_ existing history -- it's from the\nremote project I'm trying to work with.\n\nI think you'll agree there nothing wrong with a project using tags alone\nto manage its releases.\n\nHowever this means I've got to work out how to do merges of my local\nchanges onto multiple locally created branches which fork off from these\ntags.  Perhaps using this cherry-pick tool is truly the best I can do in\nthis situation.\n\n(it makes me worry though about how I might manage a super-project which\npulls from many remote sub-projects (and which includes large amounts of\nits own code) where some of those remote projects use release branches,\nand some just use tags, etc.)\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\n+1 416 218-0098                VE3TCP          RoboHack <woods@robohack.ca>\nPlanix, Inc. <woods@planix.com>      Secrets of the Weird <woods@weird.com>\n"},{"id":"128799","messageId":"20091130192212.GA23181@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFAji-000kn2C@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-11-30T19:22:12Z","receivedAt":"2009-11-30T19:22:12Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Mon, Nov 30, 2009 at 01:12:31PM -0500, Greg A. Woods wrote:\n> \n> The way \"git merge\" works does concern me somewhat though as I try to\n> figure out how I might use \"topic\" branches to develop local features\n> and then merge them onto each supported release branch.\n\nThe basic idea of using topic branches is development is done on\nseparate branches are merged to the release branch only when they are\nready to be released. These branches are based on the oldest branch in\nwhat they may be included. It means that fixes are normally based on the\nstable branch and new feature are based on the master branch, i.e. the\nbranch that contains changes for the next new feature release. Not all\nbranches got merged immediately into master. For instance, the git\nproject has 'pu' (proposed updates) and 'next' branches. Only when a new\nfeature proved itself to be useful and reliable, it is \"graduated\" to\nthe master branch. Thus the master branch is rather stable and it is\nreleased on regular intervals (no need for a long stabilization period).\n\nThe key difference comparing to what you may got used is that branches\nare normally based on the oldest branch in what this feature may be\nincluded. Thus normally changes are not backported to old branches,\nbecause you can merge them directly.\n\n\n> > Yes, you must cherry-pick or use rebase (which is a more featureful\n> > version of the pipeline you mentioned).\n> \n> \"git rebase\" will not work for me unless it grows a \"copy\" option ,\n> i.e. one which does not delete the original branch (i.e. avoids the\n> \"reset\" phase of its operation).\n\nThere is no reset phase... It is just reassigning the head of branch to\npoint to a different commit-id. If you want to copy a branch instead of\nrebasing the old one, you create a new branch (a new name) that points\nto the same commit as the branch that you want to copy, after that you\nrebase this new branch. You can do that like this:\n\n$ git branch new-foo foo\n\n$ git rebase --onto newbase oldbase new-foo\n\n> It likely wouldn't make sense to base this new \"copy\" feature directly\n> on \"git rebase\" though, especially in light of all the warnings about\n> how \"git rebase\" isn't friendly when applied to already published\n> branches.  I think in theory this \"copy\" feature won't cause problems\n> for already-published branches.\n\nThe \"copy\" does not have the problem of rebase, but it has a different\nproblem: You have two series of commits instead of one. If you found\na bug in one of those commits, you will have to patch each series\nseparately. Also, git merge may produce additional conflicts... So,\ncopying commits is not something that I would recommend to do often.\n\n\nDmitry\n"},{"id":"128806","messageId":"7vy6lnivoy.fsf@alter.siamese.dyndns.org","threadId":"21781","inReplyTo":"m1NFBAx-000kmgC@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-11-30T20:50:21Z","receivedAt":"2009-11-30T20:50:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Greg A. Woods\" <woods@planix.com> writes:\n\n> ....  This isn't really a Git problem I suppose, except\n> for the fact that it means the lack of easy support for multiple working\n> directories that track different branches makes this kind of development\n> somewhat more difficult to do with Git than with, say, CVS.\n\nYou want to google for git-new-workdir then; it is found in\ncontrib/workdir and fairly widely used.\n"},{"id":"128810","messageId":"20091130211744.GA27278@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFBAx-000kmgC@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-11-30T21:17:44Z","receivedAt":"2009-11-30T21:17:44Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Mon, Nov 30, 2009 at 01:40:38PM -0500, Greg A. Woods wrote:\n> \n> While it may be quite convenient in small projects to quickly move a\n> single working directory from one branch to another and do various\n> builds and tests from the result, large projects (say where a compile\n> takes the better part of a working day or more and where testing\n> requires multi-day processes) demand that working directories remain\n> \"stable\", and multiple lines of development therefore demand multiple\n> working directories.\n\nIt depends on the project and what tools are used, but using ccache and\nproper dependencies help a lot to reduce the cost of switching. In fact,\nit may be faster to switch to another branch and have to recompile a few\nfiles than to go into another working directory, because when you go to\nanother working directory, you hit cold cache and things get very slow.\n\nAnd then if a project is huge and takes a lot of time to compile and\ntest everything, I do not think, it is a good idea to build that in your\nwork tree. Instead, you make a shanshot using git-archive and then run\nfull build and test on it. In this way, you know that you test exactly\nwhat you have committed (you can amend any commit later until you\npublish it).\n\n\nDmitry\n"},{"id":"128825","messageId":"m1NFGXS-000kn2C@most.weird.com","threadId":"21781","inReplyTo":"20091130211744.GA27278@dpotapov.dyndns.org","subject":"Re: \"git merge\" merges too much!","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-01T00:24:14Z","receivedAt":"2009-12-01T00:24:14Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Tue, 1 Dec 2009 00:17:44 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\nSubject: Re: \"git merge\" merges too much!\n> \n> It depends on the project and what tools are used, but using ccache and\n> proper dependencies help a lot to reduce the cost of switching. In fact,\n> it may be faster to switch to another branch and have to recompile a few\n> files than to go into another working directory, because when you go to\n> another working directory, you hit cold cache and things get very slow.\n\nperhaps, sometimes, but at least with some tools that can more often\nthan not just end up with a confusing mess if you happen to change\nsomething at exactly the wrong time, and with Git it seems almost too\neasy to wildly change many files in the working directory, even if you\ncan get them back into their previous state relatively quickly\n\nThings get even weirder if you happen to be playing with older branches\ntoo -- most build tools don't have ability to follow files that go back\nin time as they assume any product files newer than the sources are\nalready up-to-date, no matter how much older the sources might become on\na second build.\n\nFrom a good software hygiene perspective the only safe way I can see to\nbuild a Git working directory after manipulating any branches with Git\nis to do a complete \"make clean && make\" cycle.  That is until Git also\nincorporates, or integrates with, really good build tools....  :-)\n\n\n> And then if a project is huge and takes a lot of time to compile and\n> test everything, I do not think, it is a good idea to build that in your\n> work tree. Instead, you make a shanshot using git-archive and then run\n> full build and test on it. In this way, you know that you test exactly\n> what you have committed (you can amend any commit later until you\n> publish it).\n \nI think this \"git-new-workdir\" script is the thing to try.  It probably\nmeans keeping separate \"configuration\" branches, one for each build\nworking directory, but I think that's OK.\n\nThese source trees are big enough that one doesn't just go throwing\naround entire copies of them willy-nilly.  Disk bandwidth is also a\nlimited resource we are very concerned about, not just disk space.\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"128833","messageId":"20091201054734.GB11235@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFGXS-000kn2C@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-12-01T05:47:34Z","receivedAt":"2009-12-01T05:47:34Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Mon, Nov 30, 2009 at 07:24:14PM -0500, Greg A. Woods wrote:\n> \n> Things get even weirder if you happen to be playing with older branches\n> too -- most build tools don't have ability to follow files that go back\n> in time as they assume any product files newer than the sources are\n> already up-to-date, no matter how much older the sources might become on\n> a second build.\n\nNo, files do not go back in time when you switch between branches. The\ntimestamp on files is the time when they are written to your working\ntree (and it is so with other VCSes that I worked with, so I do not\nknow where you get idea of file timestamps going back in time). Thus any\nbuilding tool such as 'make' should work fine provided you have correct\ndependencies. I have switched between widely diversed branches, and I\nhave never had any problem with that.\n\n\nDmitry\n"},{"id":"128906","messageId":"m1NFX19-000kn4C@most.weird.com","threadId":"21781","inReplyTo":"20091201054734.GB11235@dpotapov.dyndns.org","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-01T17:59:58Z","receivedAt":"2009-12-01T17:59:58Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Tue, 1 Dec 2009 08:47:34 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\nSubject: Re: \"git merge\" merges too much!\n> \n> On Mon, Nov 30, 2009 at 07:24:14PM -0500, Greg A. Woods wrote:\n> > \n> > Things get even weirder if you happen to be playing with older branches\n> > too -- most build tools don't have ability to follow files that go back\n> > in time as they assume any product files newer than the sources are\n> > already up-to-date, no matter how much older the sources might become on\n> > a second build.\n> \n> No, files do not go back in time when you switch between branches. The\n> timestamp on files is the time when they are written to your working\n> tree\n\nHmmm, I didn't really say anything in particular about file timestamps\n-- I meant the file content may go back in time.  More correctly I\nshould have said that the file content may become inconsistent with the\nstate of other files that have just been compiled.\n\nIf the timestamps do not get set back to commit time, but rather are\nsimply updated to move the last modify time to the time each change is\nmade to a working file (which is as you said, to be expected),\nregardless of whether its content goes back in time or not, then this\nmay or may not help a currently running build to figure out what really\nneeds to be re-compiled.  Likely it won't even for a recursive-make\nstyle update build, but certainly not for one where all build actions\nare pre-determined before any of them are started.\n\nIf the content of one or more files goes back in time to an earlier\nstate while the compile is happening then ultimately the result must be\nconsidered to be undefined.  The best you can hope for is a break in the\ncompile.\n\nThis is why I agreed with you that a build should never be done in a\nworking directory where any file editing or VCS action is occurring\nsimultaneously.\n\nI just disagreed that \"git archive\" was a reasonable alternative to\nleaving the working directory alone during the entire time of the build.\nIt is not really reasonable for large projects any more than stopping\nall work on the sources is reasonable.\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"128913","messageId":"20091201185114.GC11235@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFX19-000kn4C@most.weird.com","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-12-01T18:51:14Z","receivedAt":"2009-12-01T18:51:14Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Tue, Dec 01, 2009 at 12:59:58PM -0500, Greg A. Woods wrote:\n> At Tue, 1 Dec 2009 08:47:34 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\n> Subject: Re: \"git merge\" merges too much!\n> > \n> > On Mon, Nov 30, 2009 at 07:24:14PM -0500, Greg A. Woods wrote:\n> > > \n> > > Things get even weirder if you happen to be playing with older branches\n> > > too -- most build tools don't have ability to follow files that go back\n> > > in time as they assume any product files newer than the sources are\n> > > already up-to-date, no matter how much older the sources might become on\n> > > a second build.\n> > \n> > No, files do not go back in time when you switch between branches. The\n> > timestamp on files is the time when they are written to your working\n> > tree\n> \n> Hmmm, I didn't really say anything in particular about file timestamps\n> -- I meant the file content may go back in time.  More correctly I\n> should have said that the file content may become inconsistent with the\n> state of other files that have just been compiled.\n\nThere is no difference of content going back in time or forth. If a file\nis changed, any decent build system should recompile the corresponding\nfiles. If the build does not handle dependencies properly, you can end\nup with inconsistent state just by editing some files.\n\n> If the timestamps do not get set back to commit time, but rather are\n> simply updated to move the last modify time to the time each change is\n> made to a working file (which is as you said, to be expected),\n\nMore precisely, Git does not anything about modification time during\ncheckout. The system automatically updates the modification time when\na file is written, and Git does not mess with it.\n\n> regardless of whether its content goes back in time or not, then this\n> may or may not help a currently running build to figure out what really\n> needs to be re-compiled.\n\nObviously, switching branches while running build may produce very\nconfusing results, but it is not any different than editing files by\nhands during built -- any concurrent modification may confuse the build\nsystem.\n\n> I just disagreed that \"git archive\" was a reasonable alternative to\n> leaving the working directory alone during the entire time of the build.\n\nUsing \"git archive\" allows you avoid running long time procedure such as\nfull clean build and testing in the working tree. Also, it is guaranteed\nthat you test exactly what you put in Git and some other garbage in your\nworking tree does not affect the result. But my point was that switching\nbetween branches and recompile a few changed files may be faster than\ngoing to another working tree.\n\n\nDmitry\n"},{"id":"128914","messageId":"m1NFXpl-000knKC@most.weird.com","threadId":"21781","inReplyTo":"20091130192212.GA23181@dpotapov.dyndns.org","subject":"Re: \"git merge\" merges too much!","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-01T18:52:18Z","receivedAt":"2009-12-01T18:52:18Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Mon, 30 Nov 2009 22:22:12 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\nSubject: Re: \"git merge\" merges too much!\n> \n> The key difference comparing to what you may got used is that branches\n> are normally based on the oldest branch in what this feature may be\n> included. Thus normally changes are not backported to old branches,\n> because you can merge them directly.\n\nHmmm... the idea of creating topic branches based on the oldest branch\nwhere the feature might be used is indeed neither intuitive, nor is it\nmentioned anywhere I've so far read about using topic branches in Git.\n\nTo use topic branches effectively this way, especially in managing local\nand custom changes to a large remote project where separate working\ndirectories are needed for long-running builds, I think some additional\nsoftware configuration management tool must be used to create\n\"configuration\" branches where all the desired change sets (topic\nbranches) are merged.\n\nI spent half my dreaming time early this morning running through\nscenarios of how to use topic branches, with true merging (not\nre-basing), in a usable work-flow.\n\nAt the moment I'm leaning towards a process where the configuration\nbranch is re-created for every build -- i.e. the merges are redone from\nevery topic branch to a freshly configured branch forked from the\nlocally supported release branch, hopefully making use of git-rerere to\nsolve most conflicts in as automated a fashion as is possible.\n\nThis may not be a sane thing to do though -- it may be too much work to\ndo for every fix.  It somewhat goes against the current natural trend in\nmany of the projects I work on to develop changes on the trunk and then\nback-port (some of) them to release branches.\n\nPerhaps Stacked-Git really is the best answer.  I will have to\ninvestigate more.\n\n\n> > > Yes, you must cherry-pick or use rebase (which is a more featureful\n> > > version of the pipeline you mentioned).\n> > \n> > \"git rebase\" will not work for me unless it grows a \"copy\" option ,\n> > i.e. one which does not delete the original branch (i.e. avoids the\n> > \"reset\" phase of its operation).\n> \n> There is no reset phase...\n\nBy \"reset phase\" I meant this part, from git-rebase(1):\n\n       The current branch is reset to <upstream>, or <newbase> if the --onto\n       option was supplied. This has the exact same effect as git reset --hard\n       <upstream> (or <newbase>).\n\n\n> It is just reassigning the head of branch to\n> point to a different commit-id. If you want to copy a branch instead of\n> rebasing the old one, you create a new branch (a new name) that points\n> to the same commit as the branch that you want to copy, after that you\n> rebase this new branch. You can do that like this:\n> \n> $ git branch new-foo foo\n> \n> $ git rebase --onto newbase oldbase new-foo\n\nHmmm.... I'll have to think about that.  It makes some sense, but I\ndon't intuitively read the command-line parameters well enough to\npredict the outcome in all of the scenarios I'm interested in.\n\nwhat is \"oldbase\" there?  I'm guessing it means \"base of foo\" (and for\nthe moment, \"new-foo\" too)?\n\nIt's confusing because the manual page uses the word \"upstream\" to\ndescribe this parameter.\n\nFrom my experiments it looks like what I might want to do to copy a\nlocal branch to port its changes from one release branch to another is\nsomething like this (where local-v2.0 is a branch with local changes\nforked from release branch REL-v2.0, and I want to back-port these\nchanges to a new local branch forked from the release branch REL-v1.0):\n\n\t$ git branch local-base-v1.0 REL-v1.0\t# mark base of new branch\n\t$ git branch local-v1.0 local-v2.0\t# dup head of src branch\n\t$ git rebase --onto local-base-v1.0 REL-v2.0 local-v1.0\n\t$ git branch -d local-base-v1.0\n\nThe first and last steps may not be necessary if REL-v1.0 really is a\nbranch, but in my play project it is just a tag on the trunk.  In the\ncase that it were really already a branch then hopefully this would do:\n\n\t$ git branch local-v1.0 local-v2.0\t# dup head of src branch\n\t$ git rebase --onto REL-v1.0 REL-v2.0 local-v1.0\n\nThe trick here seems to be to invent the name of the new branch based on\nwhere it's going to be rebased to.\n\nI think this does suffice very nicely as a \"git copy\" operation!\n\n\n> The \"copy\" does not have the problem of rebase, but it has a different\n> problem: You have two series of commits instead of one. If you found\n> a bug in one of those commits, you will have to patch each series\n> separately. Also, git merge may produce additional conflicts... So,\n> copying commits is not something that I would recommend to do often.\n\nIndeed.\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\n+1 416 218-0098                VE3TCP          RoboHack <woods@robohack.ca>\nPlanix, Inc. <woods@planix.com>      Secrets of the Weird <woods@weird.com>\n"},{"id":"128916","messageId":"m1NFXvL-000kn2C@most.weird.com","threadId":"21781","inReplyTo":"20091201185114.GC11235@dpotapov.dyndns.org","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-01T18:58:05Z","receivedAt":"2009-12-01T18:58:05Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Tue, 1 Dec 2009 21:51:14 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\nSubject: Re: multiple working directories for long-running builds (was:\t\"git merge\" merges too much!)\n> \n> Obviously, switching branches while running build may produce very\n> confusing results, but it is not any different than editing files by\n> hands during built -- any concurrent modification may confuse the build\n> system.\n\nThat's what I said.  This is why multiple working directories is an\nessential feature for any significantly large project.\n\n\n> > I just disagreed that \"git archive\" was a reasonable alternative to\n> > leaving the working directory alone during the entire time of the build.\n> \n> Using \"git archive\" allows you avoid running long time procedure such as\n> full clean build and testing in the working tree. Also, it is guaranteed\n> that you test exactly what you put in Git and some other garbage in your\n> working tree does not affect the result.\n\nSure, but let's be very clear here:  \"git archive\" is likely even more\nimpossible for some large projects to use than \"git clone\" would be to\nuse to create build directories.\n\nDisk bandwidth is almost always more expensive than disk space.\n\n>   But my point was that switching\n> between branches and recompile a few changed files may be faster than\n> going to another working tree.\n\nThat's possibly going to generate even more unnecessary churn in the\nworking directory, and thus even more unnecessary re-compiles.\n\nMultiple working directories are really the only sane solution\nsometimes.\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"128924","messageId":"20091201205057.GD11235@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFXpl-000knKC@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-12-01T20:50:57Z","receivedAt":"2009-12-01T20:50:57Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Tue, Dec 01, 2009 at 01:52:18PM -0500, Greg A. Woods wrote:\n> At Mon, 30 Nov 2009 22:22:12 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\n> Subject: Re: \"git merge\" merges too much!\n> > \n> > The key difference comparing to what you may got used is that branches\n> > are normally based on the oldest branch in what this feature may be\n> > included. Thus normally changes are not backported to old branches,\n> > because you can merge them directly.\n> \n> Hmmm... the idea of creating topic branches based on the oldest branch\n> where the feature might be used is indeed neither intuitive, nor is it\n> mentioned anywhere I've so far read about using topic branches in Git.\n\nMost things that we consider \"intuitive\" are those that we got used to.\nGit is different in many aspect than other VCSes (such as CVS/SVN), and\nthe workflow that good for those VCSes may not be optimal for Git. There\nis a good description that provide basic knowledge how to use Git:\n\nman gitworkflows\n\nor online:\n\nhttp://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html\n\nIf you do not base your changes on the oldest branch then you will not\nbe able to merge changes, which implies you will have to cherry-pick\nmanually without ability automatic to track what changes were merged\nand what were not, this is a recipe for a disaster...\n\n\n> At the moment I'm leaning towards a process where the configuration\n> branch is re-created for every build -- i.e. the merges are redone from\n> every topic branch to a freshly configured branch forked from the\n> locally supported release branch, hopefully making use of git-rerere to\n> solve most conflicts in as automated a fashion as is possible.\n\nI am not quite sure that I fully understood your idea of configuration\nbranches, but I want to warn you about one serious limitations of\ngit-rerere -- it stores conflict resolution per-file basis. This means\nthat if resolution of some conflict implies some change to another file\nthen git-rerere will not help you here. So, it handles maybe 80-90%\ncases, but not all of them.\n\n> \n> Perhaps Stacked-Git really is the best answer.  I will have to\n> investigate more.\n\nThere is also TopGit. I have never used any of them, but if you are\ninterested in patch management system, you probably should look at both\nof them. StGit is modelled after quilt, while TopGit is aimed to be\nbetter integrated with Git and better fit to work in distributed\nenvironment. But as I said, I do not have any first hand experience\nwith any of them. (Personally, I would look at TopGit first, but maybe\nI am biased here).\n\n> > \n> > $ git branch new-foo foo\n> > \n> > $ git rebase --onto newbase oldbase new-foo\n> \n> Hmmm.... I'll have to think about that.  It makes some sense, but I\n> don't intuitively read the command-line parameters well enough to\n> predict the outcome in all of the scenarios I'm interested in.\n> \n> what is \"oldbase\" there?  I'm guessing it means \"base of foo\" (and for\n> the moment, \"new-foo\" too)?\n\nYou have:\n\n o---o---o---o---o  newbase\n       \\\n        o---o---o---o---o  oldbase\n                         \\\n                          o---o---o  foo\n\n\nand you want this:\n\n o---o---o---o---o  newbase\n     |            \\\n     |             o´--o´--o´  new-foo\n      \\\n       o---o---o---o---o  oldbase\n                         \\\n                          o---o---o  foo\n\n\nDmitry\n"},{"id":"128925","messageId":"20091201211830.GE11235@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFXvL-000kn2C@most.weird.com","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-12-01T21:18:30Z","receivedAt":"2009-12-01T21:18:30Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Tue, Dec 01, 2009 at 01:58:05PM -0500, Greg A. Woods wrote:\n> \n> > > I just disagreed that \"git archive\" was a reasonable alternative to\n> > > leaving the working directory alone during the entire time of the build.\n> > \n> > Using \"git archive\" allows you avoid running long time procedure such as\n> > full clean build and testing in the working tree. Also, it is guaranteed\n> > that you test exactly what you put in Git and some other garbage in your\n> > working tree does not affect the result.\n> \n> Sure, but let's be very clear here:  \"git archive\" is likely even more\n> impossible for some large projects to use than \"git clone\" would be to\n> use to create build directories.\n\nAFAIK, \"git archive\" is cheaper than git clone. I do not say it is fast\nfor huge project, but if you want to run a process such as clean build\nand test that takes a long time anyway, it does not add much to the\ntotal time.\n\n> \n> Disk bandwidth is almost always more expensive than disk space.\n\nDisk bandwidth is certainly more expensive than disk space, and the\nwhole point was to avoid a lot of disk bandwidth by using hot cache.\nIf you have two working tree then it is likely that only one will be\nin the hot cache, that is why you can switch faster (and to recompile\na few files) than going to another working tree. It has never been\nabout disk space, it is about disk cache and keeping it hot.\n\n> \n> Multiple working directories are really the only sane solution\n> sometimes.\n\nSure, sometimes... I do not know details to say what will be better in\nyour case, but I just wanted to say that you should weight that against\nswitching, because switching in Git is very fast. Much faster than with\nany other VCS...\n\nAnother thing to consider is that if you put a really huge project in one\nGit repo than Git may not be as fast as you may want, because Git tracks\nthe whole project as the whole. So, you may want to split your project in\na few relatively independent modules (See git submodule).\n\n\nDmitry\n"},{"id":"128926","messageId":"m1NFak0-000kn2C@most.weird.com","threadId":"21781","inReplyTo":"20091201205057.GD11235@dpotapov.dyndns.org","subject":"Re: \"git merge\" merges too much!","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-01T21:58:34Z","receivedAt":"2009-12-01T21:58:34Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Tue, 1 Dec 2009 23:50:57 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\nSubject: Re: \"git merge\" merges too much!\n> \n> > > \n> > > $ git branch new-foo foo\n> > > \n> > > $ git rebase --onto newbase oldbase new-foo\n> > \n> > Hmmm.... I'll have to think about that.  It makes some sense, but I\n> > don't intuitively read the command-line parameters well enough to\n> > predict the outcome in all of the scenarios I'm interested in.\n> > \n> > what is \"oldbase\" there?  I'm guessing it means \"base of foo\" (and for\n> > the moment, \"new-foo\" too)?\n> \n> You have:\n> \n>  o---o---o---o---o  newbase\n>        \\\n>         o---o---o---o---o  oldbase\n>                          \\\n>                           o---o---o  foo\n\nYes, sort of -- in the ideal situation, but not in my particular example\nwhere \"oldbase\" is just a tag, not a real branch.\n\nSo yes, \"oldbase\" is in fact \"base of foo\".  Trickier still is when the\n\"oldbase\" branch has one or more commits newer then \"base of foo\".  Does\nGit not have a symbolic name for the true base of a branch?  I.e. is\nthere not some form of symbolic name for \"N\" in the following?\n\n   o---o---o---o---o---o---o---o  master\n            \\\n             o---o---N---o---o  release-1\n                      \\\n                       o---o---o  local-release-1\n\n(now of course if it is discovered that \"release-1\" has progressed since\nthe base of \"foo\" then \"foo\" should be rebased first, but perhaps there\nis not time to do this before the other release has to be supported)\n\n\n> and you want this:\n> \n>  o---o---o---o---o  newbase\n>      |            \\\n>      |             o'--o'--o'  new-foo\n>       \\\n>        o---o---o---o---o  oldbase\n>                          \\\n>                           o---o---o  foo\n\nYes, sort of I suppose, if you trim all the non-relevant branches.\n\nWhat I really want, I think, is something like this where at least the\nnon-relevant \"master\" branch is still shown:\n\n                   1'--2'--3'  new-foo\n                  /\n         o---o---o  newbase\n        /\n   o---o---o---o---o---o---o---o  master\n                \\\n                 o---o---o  oldbase\n                          \\\n                           1---2---3  foo\n\nHere's part of my confusion -- \"newbase\" as used above is actually older\nthan \"oldbase\".  :-) so ideally \"oldbase\" should always be described in\nterms of \"foo\", not just given an arbitrary unrelated name.\n\nOf course that doesn't rule out the following scenario either where\n\"newbase\" really is newer than \"oldbase\" -- in my world a given project\nmight become locally supported first on either a newer release, or an\nolder release, so both above and below might happen:\n\n                           1'--2'--3'  new-foo\n                          /\n                 o---o---o  newbase\n                /\n   o---o---o---o---o---o---o---o  master\n        \\\n         o---o---o  oldbase\n                  \\\n                   1---2---3  foo\n\nAnd eventually I want to also merge whatever is still relevant from foo\nto a \"local\" branch off master so that those changes can be sent\n(usually as patches) upstream.\n\nSometimes I want to do development on a topic branch as close to the tip\nof \"master\" so that it can most easily be pushed upstream, and then\nback-port those changes to older release branches.\n\nIn fact the latter is exactly how I picture release branches to work in\nnormal development, and this is how several of the big projects I'd like\nto get using Git are doing development (now usually with CVS).\n\nNote too that in these kinds of projects \"topic\" branches are _always_\nforked from the current tip of \"master\", long-running ones sometimes\nrebased to keep up with \"master\", small fixes and changes are made\ndirectly to the master branch; and small fixes, as well as relevant\nfeatures, sometimes those developed on \"topic\" branches, are back-ported\nto release branches.\n\nNote I'm not talking about ideals of best practises specific for Git\nhere -- I'm talking about actual working operational practises that\npeople are _very_ familiar with and which have been well proven using a\nvast wide variety of different VCS's in the past.  For example I\nseriously doubt any of the developers of the projects I'm thinking of\nthat I'd like to switch to using Git are ever going to want to fork\ntheir topic branches from the oldest release branch base that they\nintend to support, and many such projects will necessarily always have\nat least a few long-running topic branches that will have to be\nfrequently rebased to keep up with the trunk so that their eventual\nmerging will go as smoothly as possible, and yet once any of these topic\nbranches is finally \"closed\" their changes may also have to be\nback-ported to release branches.\n\nTo me the natural way to do these kinds of back-porting \"merges\" is to\nrestrict the merge to select only the commits on the branch, i.e. from\nits base to its tip, thus the motivation for the topic of my thread (and\nI think the motivation for the \"What is the best way to backport a\nfeature?\" thread as well).  I think if Git could do this kind of\n\"partial\" merging directly without having to \"copy\" deltas with \"rebase\"\nor \"cherry-pick\" or \"am\" or whatever, and thus create separate histories\nfor them, then it would be much better at supporting this traditional\npractice of using branches to manage releases.  Without such ability it\ntruly does look as though some form of \"patch\" management tool is also a\nnecessary thing(evil?), as \"rebase\" and \"cherry-pick\" could quickly get\nway out of control and be way too much work otherwise.\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"128930","messageId":"20091201222526.GB1926@unpythonic.net","threadId":"21781","inReplyTo":"20091201211830.GE11235@dpotapov.dyndns.org","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Jeff Epler","fromEmail":"jepler@unpythonic.net","sentAt":"2009-12-01T22:25:26Z","receivedAt":"2009-12-01T22:25:26Z","isPatch":false,"sender":{"key":"jepler@unpythonic.net","avatar":"https://avatars.githubusercontent.com/u/1517291?v=4"},"body":"On Wed, Dec 02, 2009 at 12:18:30AM +0300, Dmitry Potapov wrote:\n> AFAIK, \"git archive\" is cheaper than git clone. I do not say it is fast\n> for huge project, but if you want to run a process such as clean build\n> and test that takes a long time anyway, it does not add much to the\n> total time.\n\nIf you want to keep a separate copy of your source tree in order to get\nconsistent builds, \"git archive\" is not much cheaper in disk space or in\ntime, at least on this unix system:\n\n$ find orig -exec md5sum {} + > /dev/null 2>&1 # ensure hot cache\n$ time git clone orig temp-clone\nInitialized empty Git repository in\n/usr/local/jepler/src/temp-clone/.git/\n0.6 real 0.3 user 0.6 system\n$ time (GIT_DIR=orig/.git git archive --format tar --prefix temp-archive/ HEAD | tar xf -)\n0.5 real 0.2 user 0.5 system\n$ du -s orig temp-clone temp-archive\n41880   orig\n14640   temp-clone  # du excludes files already accounted for by 'orig'\n14304   temp-archive\n\n.. and the next run to bring temp-clone up to date can be even faster,\nsince it's just 'git pull' and will only touch changed files.\n\nJeff\n"},{"id":"128931","messageId":"m1NFbSE-000kn2C@most.weird.com","threadId":"21781","inReplyTo":"20091201211830.GE11235@dpotapov.dyndns.org","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-01T22:44:15Z","receivedAt":"2009-12-01T22:44:15Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Wed, 2 Dec 2009 00:18:30 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\nSubject: Re: multiple working directories for long-running builds (was:\t\"git merge\" merges too much!)\n> \n> AFAIK, \"git archive\" is cheaper than git clone.\n\nIt depends on what you mean by \"cheaper\"  It's clearly going to require\nless disk space.  However it's also clearly going to require more disk\nbandwidth, potentially a _LOT_ more disk bandwidth.\n\n> I do not say it is fast\n> for huge project, but if you want to run a process such as clean build\n> and test that takes a long time anyway, it does not add much to the\n> total time.\n\nI think you need to try throwing around an archive of, say, 50,000 small\nfiles a few times simultaneously on your system to appreciate the issue.\n\n(i.e. consider the load on a storage subsystem, say a SAN or NAS, where\nwith your suggestion there might be a dozen or more developers running\n\"git archive\" frequently enough that even three or four might be doing\nit at the same time, and this on top of all the i/o bandwidth required\nfor the builds all of the other developers are also running at the same\ntime.)\n\n\n> > Disk bandwidth is almost always more expensive than disk space.\n> \n> Disk bandwidth is certainly more expensive than disk space, and the\n> whole point was to avoid a lot of disk bandwidth by using hot cache.\n\nHuh?  Throwing around the archive has nothing to do with the build\nsystem in this case.\n\nPlease let me worry about optimizing the builds -- that's well under\ncontrol already and is not really yet an issue for the VCS, at least\nnot yet, and maybe never in many cases.\n\nI'm just not willing to even consider using what would really be the\nmost simplistic and most expensive form of updating a working directory\nas could ever be imagined.  \"Git archive\" is truly unintelligent, as-is.\n\nPerhaps if \"git archive\" could talk intelligently to an rsync process\nand be smart about updating an existing working directory it would be\nthe ideal answer, but _NEVER_ with the current method of just unpacking\nan archive over an existing directory!  (Now there's a good Google SoC,\nor masters, project for someone eager to learn about rsync & git\ninternals!)\n\nLocal filesystem \"git clone\" is usable in many scenarios, but it just\nwon't work nearly so efficiently in a scenario where users have local\nrepos on their workstations and use an NFS NAS to feed the build\nservers.  As I understand it this 'git-new-workdir' script will work\nthough since it uses symlinks that can be pointed across the mount back\nto the local disk on the user's workstation.  They can just mount the\nbuild directory and go into it and run a \"git checkout\" and start\nanother build on the build server(s).\n\nA major further advantage of multiple working directories is that this\neliminates one more point of failure -- i.e. you don't end up with\nmultiple copies of the repo that _should_ be effectively read-only for\neverything but \"push\", and perhaps then only to one branch.  I don't\nlike giving developers too much rope, especially in all the wrong\nplaces.  \"git archive\" does achieve the same even better I suppose, but\nwithout something like a \"--format=rsync\" option it's completely out of\nthe question.\n\n\n> Another thing to consider is that if you put a really huge project in one\n> Git repo than Git may not be as fast as you may want, because Git tracks\n> the whole project as the whole. So, you may want to split your project in\n> a few relatively independent modules (See git submodule).\n\nIndeed -- but sometimes I think this is not feasible either.\n\nI know of at least three very real-world projects where there are tens\nof thousands of small files that really must be managed as one unit, and\nwhere running a build in that tree could take a whole day or two on even\nthe fastest currently available dedicated build server.  Eg. pkgsrc.\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"128938","messageId":"20091202001020.GF11235@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFbSE-000kn2C@most.weird.com","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-12-02T00:10:21Z","receivedAt":"2009-12-02T00:10:21Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Tue, Dec 01, 2009 at 05:44:15PM -0500, Greg A. Woods wrote:\n> At Wed, 2 Dec 2009 00:18:30 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\n> Subject: Re: multiple working directories for long-running builds (was:\t\"git merge\" merges too much!)\n> > \n> > AFAIK, \"git archive\" is cheaper than git clone.\n> \n> It depends on what you mean by \"cheaper\"\n\nYou said:\n\n>>> \"git archive\" is likely even more\n>>> impossible for some large projects to use than \"git clone\" \n\nMy point was that I do not see why you believe \"git archive\" is more\nexpensive than \"git clone\". Accordingly to Jeff Epler's numbers,\n\"git archive\" is 20% faster than \"git clone\"...\n\n> It's clearly going to require\n> less disk space.  However it's also clearly going to require more disk\n> bandwidth, potentially a _LOT_ more disk bandwidth.\n\nWell, it does, but as I said earlier it is not the case where I expect\nthings being instantaneous. If you do not a full build and test, then it\nis going to take a lot of time anyway, and git-archive is not likely to\nbe a big overhead in relative terms.\n\n> > I do not say it is fast\n> > for huge project, but if you want to run a process such as clean build\n> > and test that takes a long time anyway, it does not add much to the\n> > total time.\n> \n> I think you need to try throwing around an archive of, say, 50,000 small\n> files a few times simultaneously on your system to appreciate the issue.\n> \n> (i.e. consider the load on a storage subsystem, say a SAN or NAS, where\n> with your suggestion there might be a dozen or more developers running\n> \"git archive\" frequently enough that even three or four might be doing\n> it at the same time, and this on top of all the i/o bandwidth required\n> for the builds all of the other developers are also running at the same\n> time.)\n\nFirst of all, I do not see why it should be done frequently. The full\nbuild and test may be run once or twice a day, and the full test and\nbuild may take an hour. git-archive will take probably less than minute\nfor 50,000 small files (especially if you use tmpfs). In other words, it\nis 1% overhead, but you get a clean build, which is fully tested. You\ncan sure that no garbage left in the worktree that could influence the\nresult.\n\n> \n> > > Disk bandwidth is almost always more expensive than disk space.\n> > \n> > Disk bandwidth is certainly more expensive than disk space, and the\n> > whole point was to avoid a lot of disk bandwidth by using hot cache.\n> \n> Huh?  Throwing around the archive has nothing to do with the build\n> system in this case.\n\n\"git archive\" to do full build and test, which is rarely done. Normally,\nyou just switch between branches, which means a few files are changed\nand rebuild, and no archive is involved here.\n\n> \n> I'm just not willing to even consider using what would really be the\n> most simplistic and most expensive form of updating a working directory\n> as could ever be imagined.  \"Git archive\" is truly unintelligent, as-is.\n\n\"git archive\" is NOT for updating your working tree. You use \"git\ncheckout\" to switch between branches. \"git checkout\" is intelligent\nenough to overwrite only those files that actually differ between\ntwo versions.\n\n> A major further advantage of multiple working directories is that this\n> eliminates one more point of failure -- i.e. you don't end up with\n> multiple copies of the repo that _should_ be effectively read-only for\n> everything but \"push\", and perhaps then only to one branch.\n\nMultiple copies of the same repo is never a problem (except taking some\ndisks space). I really do not understand why you say that some copies\nshould be effectively read-only... You can start to work on some feature\nat one place (using one repo) and then continue in another place using\nanother repo. (Obviously, it will require to fetch changes from the\nfirst repo, before you will be able to continue, but it is just one\ncommand). In other words, I really do not understand what are you\ntalking about here.\n\n\n> \n> I know of at least three very real-world projects where there are tens\n> of thousands of small files that really must be managed as one unit, and\n> where running a build in that tree could take a whole day or two on even\n> the fastest currently available dedicated build server.  Eg. pkgsrc.\n\nTens of thousands files should not be a problem... For instance, the\nLinux kernel has around 30 thousands and Git works very well in this\ncase. But I would consider to split if it has hundrends of thousands...\n\n\nDmitry\n"},{"id":"128939","messageId":"20091202002201.GG11235@dpotapov.dyndns.org","threadId":"21781","inReplyTo":"m1NFak0-000kn2C@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-12-02T00:22:01Z","receivedAt":"2009-12-02T00:22:01Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Tue, Dec 01, 2009 at 04:58:34PM -0500, Greg A. Woods wrote:\n> At Tue, 1 Dec 2009 23:50:57 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\n> Subject: Re: \"git merge\" merges too much!\n> > \n> > > > \n> > > > $ git branch new-foo foo\n> > > > \n> > > > $ git rebase --onto newbase oldbase new-foo\n> > > \n> > > Hmmm.... I'll have to think about that.  It makes some sense, but I\n> > > don't intuitively read the command-line parameters well enough to\n> > > predict the outcome in all of the scenarios I'm interested in.\n> > > \n> > > what is \"oldbase\" there?  I'm guessing it means \"base of foo\" (and for\n> > > the moment, \"new-foo\" too)?\n> > \n> > You have:\n> > \n> >  o---o---o---o---o  newbase\n> >        \\\n> >         o---o---o---o---o  oldbase\n> >                          \\\n> >                           o---o---o  foo\n> \n> Yes, sort of -- in the ideal situation, but not in my particular example\n> where \"oldbase\" is just a tag, not a real branch.\n\nIt does not matter whether it is tag or branch or just SHA-1. You can\nuse any two reference as newbase and oldbase. They specify two points\nin DAG. The only thing that has to be a branch in my example is new-foo.\n\n> \n> So yes, \"oldbase\" is in fact \"base of foo\".  Trickier still is when the\n> \"oldbase\" branch has one or more commits newer then \"base of foo\".  Does\n> Git not have a symbolic name for the true base of a branch?  I.e. is\n> there not some form of symbolic name for \"N\" in the following?\n> \n>    o---o---o---o---o---o---o---o  master\n>             \\\n>              o---o---N---o---o  release-1\n>                       \\\n>                        o---o---o  local-release-1\n\nYou can always find SHA-1 for N using the following command:\n\n  git merge-base release-1 local-release-1\n\nbut you do not have to do that to rebase your changes. You just can run:\n\n   # create a copy of local-release-1, so it will not disappear\n   git branch copy-release-1 local-release-1\n\n   # rebase the branch to master\n   git rebase --onto master release-1 copy-release-1\n\n\nDmitry\n"},{"id":"128949","messageId":"7viqcqp1nh.fsf@alter.siamese.dyndns.org","threadId":"21781","inReplyTo":"20091201211830.GE11235@dpotapov.dyndns.org","subject":"Re: multiple working directories for long-running builds","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-02T02:09:38Z","receivedAt":"2009-12-02T02:09:38Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dmitry Potapov <dpotapov@gmail.com> writes:\n\n> On Tue, Dec 01, 2009 at 01:58:05PM -0500, Greg A. Woods wrote:\n>> \n>> > > I just disagreed that \"git archive\" was a reasonable alternative to\n>> > > leaving the working directory alone during the entire time of the build.\n>> > \n>> > Using \"git archive\" allows you avoid running long time procedure such as\n>> > full clean build and testing in the working tree. Also, it is guaranteed\n>> > that you test exactly what you put in Git and some other garbage in your\n>> > working tree does not affect the result.\n>> \n>> Sure, but let's be very clear here:  \"git archive\" is likely even more\n>> impossible for some large projects to use than \"git clone\" would be to\n>> use to create build directories.\n>\n> AFAIK, \"git archive\" is cheaper than git clone. I do not say it is fast\n> for huge project, but if you want to run a process such as clean build\n> and test that takes a long time anyway, it does not add much to the\n> total time.\n\nI do not understand people who advocate for \"git archive\" to be used in\nthis manner at all.\n\nI do use a set of separate build directories, and I typically run 5 to 10\nfull builds (in each) per day, but I rarely if ever make fix in them.\nPerhaps the usage pattern expected by people who want others to use \"git\narchive\" to prepare separate build directories may be different from how I\nuse them for.\n\nI see two downsides in using \"git archive\":\n\n - \"archive\" piped to \"tar xf -\" will overwrite _all_ files every time you\n   refresh the build area, causing extra work on \"make\" and any build\n   procedure based on file timestamps.  Sure, you can work it around by\n   using ccache but why make your life complicated?\n\n - When a build in these separate build areas fails, you would want to go\n   there and try to diagnose or even fix the problem in there, not in your\n   primary working area (after all, the whole point of keeping a separate\n   build area is so that you do not have to switch branches too much in\n   the primary working area).  A directory structure prepared by \"archive\"\n   piped to \"tar xf -\" however is not a work tree, and any experimental\n   changes (e.g. \"debugf()\") or fixes you make there need to be reverted\n   or taken back manually to be placed in the primary working area.\n\nIf your build area is prepared with new-workdir, then you share the\nhistory and you even share the ref namespace, so that \"reset --hard\" will\nremove all the debugf() added while diagnosing, and \"diff\" will give you\nthe patch you need to take home.\n\nYou could even make a commit from your build area, but this cuts both\nways.  You need to be aware that after committing on a branch in one\nrepository other repositories that have the same branch checked out will\nbecome out of sync.  It is however less of an issue in practice, because\nthe build areas are typically used to check out integration branches\n(e.g. 'master' and 'next' in git.git) that you do not directly commit\nanyway, and you will get very aware of the tentative nature of the tree,\nas the update procedure for such a build area prepared with new-workdir is\nalways:\n\n    cd /buildfarm/<branch>/ && git reset --hard\n\nThis will not touch any file that do not have to get updated, so your\n\"make\" won't get confused.\n"},{"id":"128990","messageId":"20091202192021.6117@nanako3.lavabit.com","threadId":"21781","inReplyTo":"m1NFXpl-000knKC@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2009-12-02T10:20:21Z","receivedAt":"2009-12-02T10:20:21Z","isPatch":false,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Quoting \"Greg A. Woods\" <woods@planix.com> writes:\n\n> At Mon, 30 Nov 2009 22:22:12 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\n> Subject: Re: \"git merge\" merges too much!\n>> \n>> The key difference comparing to what you may got used is that branches\n>> are normally based on the oldest branch in what this feature may be\n>> included. Thus normally changes are not backported to old branches,\n>> because you can merge them directly.\n>\n> Hmmm... the idea of creating topic branches based on the oldest branch\n> where the feature might be used is indeed neither intuitive, nor is it\n> mentioned anywhere I've so far read about using topic branches in Git.\n\nYou may want to add the result of googling \n\n  \"Fun with\" site:gitster.livejournal.com\n\nto the list of Git documents you read. \"Fork from the oldest \nbranch\" is one of the techniques Junio teaches often and many \nof his other techiniques are built upon.\n\nHe not just teaches useful techniques but explains a lot about \nthe reasoning behind them in his Git book. His blog articles \nhave the same explanations on many topics I saw in his book \nbut not in other places. It is a useful substitute until his \nbook gets translated to English for people who don't read \nJapanese.\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"129060","messageId":"20091202200904.GA7631@coredump.intra.peff.net","threadId":"21781","inReplyTo":"m1NFAji-000kn2C@most.weird.com","subject":"Re: \"git merge\" merges too much!","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-12-02T20:09:04Z","receivedAt":"2009-12-02T20:09:04Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Nov 30, 2009 at 01:12:31PM -0500, Greg A. Woods wrote:\n\n> (From a first pass through the documentation I would never have guessed\n> that \"tags\" were also a form of \"refs\".  All these different names for\n\nI find git is much simpler to use and understand if you start \"at the\nbottom\" with the basic concepts (because for the most part, git is\nreally a set of tools for manipulating the few basic data structures).\nFor a short intro, try:\n\n  http://eagain.net/articles/git-for-computer-scientists/\n\nI think Scott Chacon's \"Pro Git\" book also takes a similar approach, but\nI confess that I have not actually read it carefully. At this point, I\nknow enough about git to make reading it not very interesting. :) You\ncan find it online at:\n\n  http://progit.org/book/\n\n> features.  Even the gitglossary(7) is somewhat inconsistent on how it\n> uses \"ref\" and \"refs\".  Perhaps all that's needed is some firm editing\n> and clean-up of the manuals and documentation by a good strong technical\n> editor.)\n\nI skimmed it and didn't see any inconsistency. If you have something\nspecific in mind, please point it out so we can fix it.\n\n> \"git rebase\" will not work for me unless it grows a \"copy\" option ,\n> i.e. one which does not delete the original branch (i.e. avoids the\n> \"reset\" phase of its operation).  This option would likely only make\n> sense when used with the \"--onto\" option, I would guess.\n\nI think Dmitry already mentioned this, but you probably want to create a\nnew branch to hold your rebased history if you don't want to modify the\nexisting branch.\n\n> (git-log(1) is worse than ls(1) for having too many options, but worst\n> of all in the release I'm still using it doesn't respond sensibly nor\n> consistently with other commands when given the \"-?\" option.)\n\n$ ls -?\nls: invalid option -- '?'\nTry `ls --help' for more information.\n\n$ ls --help ;# or ls -h\n[copious usage information]\n\n$ git log -?\nfatal: unrecognized argument: -?\n\n$ git log --help\n[the man page]\n\n$ git log -h\nusage: git log [<options>] [<since>..<until>] [[--] <path>...]\n   or: git show [options] <object>...\n\n$ cd /outside/of/git/repo\n$ git log -?\nfatal: Not a git repository (or any of the parent directories): .git\n\nSo \"-?\" is bogus for both ls and git. But there are two failings I see:\n\n  1. Outside of a repository, \"git log\" does not even get to the\n     argument-parsing phase to see that \"-?\" is bogus. We short-circuit\n     \"-h\" and \"--help\" to avoid actually looking for a git repository,\n     but obviously cannot do so for every \"--bogus\" argument we see.\n     We could potentially also short-circuit \"-?\" (and probably map it\n     to \"-h\" if we were going to do that). However, I didn't think \"-?\"\n     was in common use.\n\n  2. \"git log -h\" doesn't mention any of the options specifically,\n     though other git commands do (e.g., try \"git archive -h\"). This is\n     because the option list is generated by our parseopt library, but\n     the revision and diff options (which are the only ones that \"git\n     log\" takes) do not use parseopt. Maybe we should point to \"--help\"\n     for the full list in that case.\n\n-Peff\n"},{"id":"129089","messageId":"m1NG0O6-000kmgC@most.weird.com","threadId":"21781","inReplyTo":"20091202200904.GA7631@coredump.intra.peff.net","subject":"Re: Git documentation consistency (was: \"git merge\" merges too much!)","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-03T01:21:39Z","receivedAt":"2009-12-03T01:21:39Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Wed, 2 Dec 2009 15:09:04 -0500, Jeff King <peff@peff.net> wrote:\nSubject: Re: \"git merge\" merges too much!\n> \n> I find git is much simpler to use and understand if you start \"at the\n> bottom\" with the basic concepts (because for the most part, git is\n> really a set of tools for manipulating the few basic data structures).\n\nI think that's the problem actually -- I don't really want to know too\nmuch about how it works under the hood (yet), I just want to use it in\nthe most effective way for my purposes.\n\nThere's lots of talk about using Git as the basis for a true high-level\nVCS and SCM system, yet it doesn't look to me that anyone has created\nsuch a VCS or SCMS using Git.\n\n\n> I skimmed it and didn't see any inconsistency. If you have something\n> specific in mind, please point it out so we can fix it.\n\nI think anyone who's been participating on this list for any significant\namount of time is far too close to the subject to be able to serve as a\ncandid independent technical editor who could really help clean things\nup and make the documentation much more consistent.  Obviously such an\neditor would also require the help of experts at all the details too. :-)\n\nUnfortunately I'm not a very good technical editor, and I don't really\nhave time to devote to doing such editing of documentation either.\n\n\n> > (git-log(1) is worse than ls(1) for having too many options, but worst\n> > of all in the release I'm still using it doesn't respond sensibly nor\n> > consistently with other commands when given the \"-?\" option.)\n> \n> $ ls -?\n> ls: invalid option -- '?'\n> Try `ls --help' for more information.\n\nPlease keep in mind all the world is not GNU:\n\n\t$ ls -?\n\tls: unknown option -- ?\n\tusage: ls [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]\n\nMy point was that _most_ other Git sub-commands already do respond to\n\"-?\" sensibly with real, helpful, information; usually a summary of the\ncommand options and parameters.\n\nI.e. this is yet another form of inconsistency in \"documentation\" in\nGit.  :-)\n\nThe reference to \"ls\" was just as a comparison with it's somewhat\nextensive variety of options.  In fact \"git log\" is way more complex\nthan \"ls\" because its parameters are not all just simple flags like\nthose for \"ls\" -- they often have their own parameters too.\n\n\n> $ git log -h\n> usage: git log [<options>] [<since>..<until>] [[--] <path>...]\n>    or: git show [options] <object>...\n\nIndeed, so why the heck can't it do something similar with '-?'.  That's\njust sloppy programming, no?  Most other commands know '-?', and despite\nthe silliness with GNU Ls, use of '-?' to request summary usage\ninformation is pretty much a de facto standard for unix commands.\n\nYour point about mentioning \"--help\" in the summary usage information is\na good one though -- especially for a command with a very complex set of\ncommand-line parameters.  However that alone isn't sufficient -- users\nstill need the summary as that alone helps trigger associations and may\nbe sufficient to allow a user to proceed quickly to get the command to\ndo what they want.\n\n\n(the whole \"fatal: not a git repository\" error for \"git foo -[h?]\"\nhandling is also a rather silly one -- but I guess when something grows\nquickly and from many inputs there's not always time to keep some of\nthese basic things clean and consistent)\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"129090","messageId":"7vaay096ye.fsf@alter.siamese.dyndns.org","threadId":"21781","inReplyTo":"m1NG0O6-000kmgC@most.weird.com","subject":"Re: Git documentation consistency","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-03T01:34:01Z","receivedAt":"2009-12-03T01:34:01Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Greg A. Woods\" <woods@planix.com> writes:\n\n> \t$ ls -?\n> \tls: unknown option -- ?\n> \tusage: ls [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]\n> ...\n> Most other commands know '-?', and despite\n> the silliness with GNU Ls, use of '-?' to request summary usage\n> information is pretty much a de facto standard for unix commands.\n\nI think you are showing ignorance here, as -? is *not* even close to\nstandard, nor even widely used practice at all.  I somehow doubt your ls\nwould respond to \"ls -X\" any differently from \"ls -?\", but is giving the\nsame canned response to any unknown option.\n\nThe \"usage: ls [-AaBbC...] [file...]\" indeed is much better than abstract\n\"usage: frotz <options> <args>\" that does not list what <options> are, but\nthat is a totally different thing.  On that point, I think Peff already\nmade a good suggestion of giving the full help text in such a case.\n"},{"id":"129093","messageId":"20091203020711.GB12061@coredump.intra.peff.net","threadId":"21781","inReplyTo":"m1NG0O6-000kmgC@most.weird.com","subject":"Re: Git documentation consistency (was: \"git merge\" merges too much!)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-12-03T02:07:11Z","receivedAt":"2009-12-03T02:07:11Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Dec 02, 2009 at 08:21:39PM -0500, Greg A. Woods wrote:\n\n> > I find git is much simpler to use and understand if you start \"at the\n> > bottom\" with the basic concepts (because for the most part, git is\n> > really a set of tools for manipulating the few basic data structures).\n> \n> I think that's the problem actually -- I don't really want to know too\n> much about how it works under the hood (yet), I just want to use it in\n> the most effective way for my purposes.\n>\n> There's lots of talk about using Git as the basis for a true high-level\n> VCS and SCM system, yet it doesn't look to me that anyone has created\n> such a VCS or SCMS using Git.\n\nSure, I can understand that. And I invite you (or anyone) to work on\nsuch a VCS, and I am sure I am not alone on the list in sincerely hoping\nyou succeed and offering to help support however core git developers\ncan. But we have seen people try this in the past, and it never quite\nseems to work.\n\nAll of the cogito people ended up migrating to git. I was one of them.\nIn my case, the git tools offered better access to the fundamental\noperations, which is what I found interesting and powerful about it. I\nsuspect some others migrated for the same reasons, though perhaps many\ndid simply because cogito did not keep up with core git in terms of\nfeatures.\n\nThere is also \"eg\" these days, which attempts to do what you're saying.\nI don't know how big a userbase it has; I've never been personally\ninterested in it.\n\n> I think anyone who's been participating on this list for any significant\n> amount of time is far too close to the subject to be able to serve as a\n> candid independent technical editor who could really help clean things\n> up and make the documentation much more consistent.  Obviously such an\n> editor would also require the help of experts at all the details too. :-)\n\nSure, I think an outsider doing a really nice job of overhauling the\ndocumentation would be nice. There are some git books, some by insiders,\nand some not. For the same reason that you mention, it would hard for me\nto assess their quality with too much objectivity. :)\n\nMy question was more of a \"leaving aside overhauling the documentation,\ndid you see something obvious that we can fix right now\" kind of thing.\n\n> > $ ls -?\n> > ls: invalid option -- '?'\n> > Try `ls --help' for more information.\n> \n> Please keep in mind all the world is not GNU:\n> \n> \t$ ls -?\n> \tls: unknown option -- ?\n> \tusage: ls [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]\n\nRight, but my point is unchanged. Neither ls actually _recognizes_\n\"-?\". They do the same for \"--bogosity\".\n\n> My point was that _most_ other Git sub-commands already do respond to\n> \"-?\" sensibly with real, helpful, information; usually a summary of the\n> command options and parameters.\n\nYes, for the same reason that \"ls\" does: they don't recognize it. But if\nyou are asking for \"git log\" to produce the short usage message, then\nthat is part of my issue (1) from the last message: \"log\" doesn't use\nthe same parseopt library as (most of) the rest of git[1].\n\nYes, it's inconsistent. Those inconsistencies were introduced over time\n(before we had parseopt), and we are slowly fixing them over time.\nPatches welcome. :)\n\n[1] There are other inconsistencies because of this, too. You can't say\n\"git log -pz\", but must say \"git log -p -z\".\n\n> > $ git log -h\n> > usage: git log [<options>] [<since>..<until>] [[--] <path>...]\n> >    or: git show [options] <object>...\n> \n> Indeed, so why the heck can't it do something similar with '-?'.  That's\n> just sloppy programming, no?  Most other commands know '-?', and despite\n> the silliness with GNU Ls, use of '-?' to request summary usage\n> information is pretty much a de facto standard for unix commands.\n\nNothing \"knows\" -?, but it is true that the parseopt-ified commands\nbehave differently (and IMHO, better). You can call it sloppy, I guess;\nit is really an artifact of commands being written and changing over\ntime. As I said, we are slowly converging on consistency.\n\nAnd no, I don't want to get into a big debate over whether it is better\nto plan your software up front, or to let it evolve over time. I have\nopinions that do not necessarily line up with how git came into being,\nbut the end product is useful enough that I like to use it and hack on\nit. :)\n\n> (the whole \"fatal: not a git repository\" error for \"git foo -[h?]\"\n> handling is also a rather silly one -- but I guess when something grows\n> quickly and from many inputs there's not always time to keep some of\n> these basic things clean and consistent)\n\nThe problem here is that there are two chunks of code: the \"git\"\nwrapper, and the \"log\" command. The wrapper knows a few things about\neach command like \"does it need to be in a git repository?\", and checks\nthat before we even look at the command-line options. There is an\nexplicit \"check for --help\" hack. Fixing that startup procedure to be\nmore sane would be possible, but there are a lot of hidden demons\nlurking in changing the order of the startup sequence. Again, patches\nwelcome. :)\n\n-Peff\n"},{"id":"129097","messageId":"m1NG3yC-000kmgC@most.weird.com","threadId":"21781","inReplyTo":"20091202001020.GF11235@dpotapov.dyndns.org","subject":"Re: multiple working directories for long-running builds (was: \"git merge\" merges too much!)","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-03T05:11:09Z","receivedAt":"2009-12-03T05:11:09Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Wed, 2 Dec 2009 03:10:21 +0300, Dmitry Potapov <dpotapov@gmail.com> wrote:\nSubject: Re: multiple working directories for long-running builds (was:\t\"git merge\" merges too much!)\n> \n> My point was that I do not see why you believe \"git archive\" is more\n> expensive than \"git clone\". Accordingly to Jeff Epler's numbers,\n> \"git archive\" is 20% faster than \"git clone\"...\n\nReally!?!?!?  You don't see it?  Why is this so hard to understand?\nSorry for my incredulity, but I thought this issue was obvious.\n\nThe slightly more expensive \"git clone\" happens only _ONCE_.  After that\nyou just run \"git pull\" I think (plus maybe \"git reset --hard\"?), but in\nany case it's a heck of a lot less I/O and CPU than \"git archive\".\n\nAnd of course you skip even the one-time \"git clone\" operation if you\nuse the even faster and simpler git-new-workdir script.\n\n\"git archive\" has to be run _EVERY_ time you need to update a working\ndirectory and it currently has no choice but to toss every bit of the\nwhole working directory, up from the filesystem, across a pipe, and back\ndown to the filesystem.  It literally couldn't be more expensive!\n\nSure, no matter how you do it, updating the working directory might not\nalways be the biggest part of the operation, but it's insane to use the\nmost expensive mechanism ever possible when there are far cheaper\nalternatives.\n\nBTW, there cannot, and MUST NOT, be any integrity advantage to using\n\"git archive\" over using multiple working directories.  \"git archive\nbranch\" must, by definition, produce exactly the same result as if you\ndid \"git checkout branch; rm -rf .git\" or else it is buggy.\n\nNote also that the build directories created with git-new-workdir can be\ntreated as read-only, and perhaps even forced to be read-only by mount\noptions or maybe just by a corporate policy directive.  (in all projects\nI'm working on the source tree can be read-only -- product files are\nalways generated elsewhere)\n\n\n> Multiple copies of the same repo is never a problem (except taking some\n> disks space).\n\nExactly -- gigabytes of disk space per copy in the cases I'm concerned\nabout (i.e. where hard links are impossible).  I've heard that at least\none very large project has an 8GB repository currently.  Three of the\nlarge projects I work on now are about a gigabyte per copy.  That's just\nwhat's under .git too, not including the whole working directory as\nwell.  I can't even manage a \"git clone\" from HTTP of one of them\nwithout increasing my default process limits as it is so big and uses up\ntoo much memory.\n\nI guess one could skip the initial more-expensive \"git clone\" operation\nby copying the repo using low-level bit moving commands, like \"cp -r\" or\nwhatever, and then tweak the result to make it appear as if it had been\ncloned, but even that requires moving gigabytes of data unnecessarily\nacross what is likely to be a network connection of some sort.\n\nAre you fighting against git-new-workdir, or the concept of multiple\nworking directories?\n\n\n> > A major further advantage of multiple working directories is that this\n> > eliminates one more point of failure -- i.e. you don't end up with\n> > multiple copies of the repo that _should_ be effectively read-only for\n> > everything but \"push\", and perhaps then only to one branch.\n> \n> I really do not understand why you say that some copies\n> should be effectively read-only... You can start to work on some feature\n> at one place (using one repo) and then continue in another place using\n> another repo. (Obviously, it will require to fetch changes from the\n> first repo, before you will be able to continue, but it is just one\n> command). In other words, I really do not understand what are you\n> talking about here.\n\nDevelopers, especially more junior ones, work on code, and they (are\nsupposed to) spend almost all of their intellectual energy on the issues\nto do with creating and modifying code -- they are not expected to be\nintegration engineers, nor are they expected to be VCS and SCM experts.\n\nThe more steps you put in place for them to do, and the more places you\nallow them to store changes, etc., etc., etc., the more mistakes that\nthey will make.\n\nBesides, in some scenarios build directories will be checked out from\nintegration branches which shouldn't have any direct commits made to\nthem, especially not to fix a problem in a build.\n\n\nBTW, pkgsrc has well over 50,000 files, FreeBSD ports is over 100,000.\nNeither can really be split in any rational way.\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"129104","messageId":"m1NG61U-000kn4C@most.weird.com","threadId":"21781","inReplyTo":"7vaay096ye.fsf@alter.siamese.dyndns.org","subject":"Re: Git documentation consistency","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-03T07:22:41Z","receivedAt":"2009-12-03T07:22:41Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Wed, 02 Dec 2009 17:34:01 -0800, Junio C Hamano <gitster@pobox.com> wrote:\nSubject: Re: Git documentation consistency\n> \n> I think you are showing ignorance here, as -? is *not* even close to\n> standard, nor even widely used practice at all.\n\nI think I should know something about Unix command line and option\nparsers, having used them for some 25 years or so now.  In fact I've\nused most every kind of unix that ever was, and I've worked on the\nsource to more than a few.\n\n\n>  I somehow doubt your ls\n> would respond to \"ls -X\" any differently from \"ls -?\", but is giving the\n> same canned response to any unknown option.\n\nIndeed.  Whether it is useful for \"-?\" to give a more detailed summary\nthan the basic one-line usage message often depends on how complex the\ncommand-line features are.  My preference is for '-?' (and if possible\n'-h' as well) to give detailed usage info, though hopefully limited to\njust one screen full if possible (though with Git's free use of $PAGER\nin many contexts it might be OK to feed longer usage info to $PAGER\ntoo).\n\nSo, the basic usage messages for command-line \"syntax\" problems should\nbe a one-line summary (following the error message).\n\nIf more detail could be useful then '-?' (and if possible '-h') should\ndisplay a more detailed usage message.  (and if one line suffices then\n'-?' and '-h' don't really have to be treated specially)\n\n\n> The \"usage: ls [-AaBbC...] [file...]\" indeed is much better than abstract\n> \"usage: frotz <options> <args>\" that does not list what <options> are, but\n> that is a totally different thing.  On that point, I think Peff already\n> made a good suggestion of giving the full help text in such a case.\n\nIndeed the abstract content-free \"<options>\" style message is almost\nuseless in most cases.\n\nIt would also be useful to reflect in the usage message what the driver\nprogram saw as its argv[0], not what the internal command saw:\n\n$ git rebase -X\nUsage: /usr/pkg/libexec/git-core//git-rebase [--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]\n\n\nOr perhaps this could be cleaned up with something as simple as always\nstripping off the pathname with the likes of:\n\n     argv0 = (argv0 = strrchr(argv[0], '/')) ? argv0 + 1 : argv[0];\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"},{"id":"129106","messageId":"20091203074500.GA31566@coredump.intra.peff.net","threadId":"21781","inReplyTo":"m1NG61U-000kn4C@most.weird.com","subject":"Re: Git documentation consistency","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-12-03T07:45:00Z","receivedAt":"2009-12-03T07:45:00Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Dec 03, 2009 at 02:22:41AM -0500, Greg A. Woods wrote:\n\n> > I think you are showing ignorance here, as -? is *not* even close to\n> > standard, nor even widely used practice at all.\n> \n> I think I should know something about Unix command line and option\n> parsers, having used them for some 25 years or so now.  In fact I've\n> used most every kind of unix that ever was, and I've worked on the\n> source to more than a few.\n\nI don't want to nitpick, because the main thrust of your point (that\n\"git foo --bogus\" should show a more useful message) is not affected by\nthis subpoint at all.  But if we are considering special-casing \"-?\", I\nwould like to see some evidence that it is actually in use.\n\nI can't seem to find it respected anywhere, as shown below (and note\nthat yes, some of this output does show a useful help message, but that\nis because --bogus would show the same message, and I am not disputing\nthat we should handle that case):\n\n# My linux box\n$ uname -sr\nLinux 2.6.31-1-686\n$ ls -?\nls: invalid option -- '?'\nTry `ls --help' for more information.\n\n# Solaris\n$ uname -sr\nSunOS 5.8\n$ /bin/ls -?\n/bin/ls: illegal option -- ?\nusage: ls -1RaAdCxmnlogrtucpFbqisfL [files]\n$ /usr/ucb/ls -? ;# appears to ignore bogus options entirely?\nfoo\n$ /usr/ucb/fold -?\n/usr/ucb/fold: illegal option -- ?\nUsage: fold [-bs] [-w width | -width ] [file...]\n$ /usr/xpg4/bin/ls -?\n/usr/xpg4/bin/ls: illegal option -- ?\nusage: ls -1RaAdCxmnlogrtucpFbqisfL [files]\n$ /usr/xpg6/bin/ls -?\nbash: /usr/xpg6/bin/ls: No such file or directory\n\n# AIX\n$ uname -svr\nAIX 1 6\n$ /bin/ls -?\n/bin/ls: illegal option -- ?\nusage: ls [-1ACFHLNRabcdefgilmnopqrstuxEUX] [File...]\n\nSo what systems _do_ treat \"-?\" specially?\n\n-Peff\n"},{"id":"129122","messageId":"6839293b0912030724y1c794606w3f2b191b3123a542@mail.gmail.com","threadId":"21781","inReplyTo":"20091203074500.GA31566@coredump.intra.peff.net","subject":"Re: Git documentation consistency","fromName":"Uri Okrent","fromEmail":"uokrent@gmail.com","sentAt":"2009-12-03T15:24:30Z","receivedAt":"2009-12-03T15:24:30Z","isPatch":false,"sender":{"key":"uokrent@gmail.com","avatar":"https://gravatar.com/avatar/7788ed2d4f1bfefc11082b08b0234fd2d752113623753bda4a032a2ae9687acf?d=mp&s=160"},"body":"On Wed, Dec 2, 2009 at 11:45 PM, Jeff King <peff@peff.net> wrote:\n> So what systems _do_ treat \"-?\" specially?\n>\n> -Peff\n\nWindows seems to (of course you need to use '/' instead of '-'):\n\nMicrosoft Windows [Version 6.0.6001]\n\nc:\\>dir -h\n Volume in drive C has no label.\n Volume Serial Number is B09A-B49F\n\n Directory of c:\\\n\nFile Not Found\n\nc:\\>dir /h\nInvalid switch - \"h\".\n\nc:\\>dir /help\nInvalid switch - \"help\".\n\nc:\\>dir /?\nDisplays a list of files and subdirectories in a directory.\n\nDIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]\n  [/O[[:]sortorder]] [/P] [/Q] [/R] [/S] [/T[[:]timefield]] [/W] [/X] [/4]\n\n  [drive:][path][filename]\n              Specifies drive, directory, and/or files to list.\n\n  /A          Displays files with specified attributes.\n  attributes   D  Directories                R  Read-only files\n               H  Hidden files               A  Files ready for archiving\n               S  System files               I  Not content indexed files\n               L  Reparse Points             -  Prefix meaning not\n  /B          Uses bare format (no heading information or summary).\n  /C          Display the thousand separator in file sizes.  This is the\n              default.  Use /-C to disable display of separator.\n  /D          Same as wide but files are list sorted by column.\n  /L          Uses lowercase.\n  /N          New long list format where filenames are on the far right.\n  /O          List by files in sorted order.\n  sortorder    N  By name (alphabetic)       S  By size (smallest first)\n               E  By extension (alphabetic)  D  By date/time (oldest first)\n               G  Group directories first    -  Prefix to reverse order\n  /P          Pauses after each screenful of information.\n  /Q          Display the owner of the file.\n  /R          Display alternate data streams of the file.\n  /S          Displays files in specified directory and all subdirectories.\n  /T          Controls which time field displayed or used for sorting\n  timefield   C  Creation\n              A  Last Access\n              W  Last Written\n  /W          Uses wide list format.\n  /X          This displays the short names generated for non-8dot3 file\n              names.  The format is that of /N with the short name inserted\n              before the long name. If no short name is present, blanks are\n              displayed in its place.\n  /4          Displays four-digit years\n\nSwitches may be preset in the DIRCMD environment variable.  Override\npreset switches by prefixing any switch with - (hyphen)--for example, /-W.\n\nc:\\>\n\n-- \n   Uri\n\nPlease consider the environment before printing this message.\nhttp://www.panda.org/how_you_can_help/\n"},{"id":"129125","messageId":"e51f66da0912030822ye1541b4gb1b8a3e07eb72484@mail.gmail.com","threadId":"21781","inReplyTo":"m1NG61U-000kn4C@most.weird.com","subject":"Re: Git documentation consistency","fromName":"Marko Kreen","fromEmail":"markokr@gmail.com","sentAt":"2009-12-03T16:22:27Z","receivedAt":"2009-12-03T16:22:27Z","isPatch":false,"sender":{"key":"markokr@gmail.com","avatar":null},"body":"On 12/3/09, Greg A. Woods <woods@planix.com> wrote:\n> At Wed, 02 Dec 2009 17:34:01 -0800, Junio C Hamano <gitster@pobox.com> wrote:\n>  Subject: Re: Git documentation consistency\n>  > I think you are showing ignorance here, as -? is *not* even close to\n>  > standard, nor even widely used practice at all.\n>\n>  I think I should know something about Unix command line and option\n>  parsers, having used them for some 25 years or so now.  In fact I've\n>  used most every kind of unix that ever was, and I've worked on the\n>  source to more than a few.\n\n'?' is what getopt(3) is supposed to return for unknown options.\n\n-- \nmarko\n"},{"id":"129658","messageId":"m1NISeX-000kmuC@most.weird.com","threadId":"21781","inReplyTo":"e51f66da0912030822ye1541b4gb1b8a3e07eb72484@mail.gmail.com","subject":"Re: Git documentation consistency","fromName":"Greg A. Woods","fromEmail":"woods@planix.com","sentAt":"2009-12-09T19:56:46Z","receivedAt":"2009-12-09T19:56:46Z","isPatch":false,"sender":{"key":"woods@planix.com","avatar":null},"body":"At Thu, 3 Dec 2009 18:22:27 +0200, Marko Kreen <markokr@gmail.com> wrote:\nSubject: Re: Git documentation consistency\n> \n> On 12/3/09, Greg A. Woods <woods@planix.com> wrote:\n> > At Wed, 02 Dec 2009 17:34:01 -0800, Junio C Hamano <gitster@pobox.com> wrote:\n> >  Subject: Re: Git documentation consistency\n> >  > I think you are showing ignorance here, as -? is *not* even close to\n> >  > standard, nor even widely used practice at all.\n> >\n> >  I think I should know something about Unix command line and option\n> >  parsers, having used them for some 25 years or so now.  In fact I've\n> >  used most every kind of unix that ever was, and I've worked on the\n> >  source to more than a few.\n> \n> '?' is what getopt(3) is supposed to return for unknown options.\n\nIndeed, which is why it cannot ever, in general, be used as a valid\noption with some command-specific meaning, and so why the one-line form\nof the usage message should always be displayed when the user explicitly\ngives a '-?' option (i.e. in the same way as if any unknown option is\ngiven).\n\nIf the one-line usage message is too terse to explain more complex\ncommand line syntax then '-h' (and --help) should display a short\nmulti-line summary of the command's usage.\n\nI guess what I should have suggested in the first place is that all Git\nsub-commands should respond with a one-line[*] usage message when they\nencounter an unknown option, such as '-?', and that they should (only)\ndisplay a more detailed multi-line help summary when given '-h' or\n'--help' options.\n\nI was most surprised when I didn't get a one-line usage summary from\n\"git log -?\", just getopt(3)'s error message.\n\n[*] commands which have multiple distinct modes of operation with\nseparate and unique command-line syntax for each mode, should of course\ndisplay a one-line summary for each command mode, such as in this\nexample:\n\nvoid\nusage(void)\n{\n\tfprintf(stderr, \"Usage:  %s [-abcdef]\\n\", getprogname());\n\tfprintf(stderr, \"        %s [-l]\\n\", getprogname());\n\texit(2);\n}\n\n\n-- \n\t\t\t\t\t\tGreg A. Woods\n\t\t\t\t\t\tPlanix, Inc.\n\n<woods@planix.com>       +1 416 218 0099        http://www.planix.com/\n"}]}