{"thread":{"id":"20892","subject":"obnoxious CLI complaints","startedAt":"2009-09-09T21:27:56Z","lastAt":"2009-09-17T01:27:18Z","messageCount":46,"participants":["Brendan Miller","Jakub Narebski","Sverre Rabbelier","Wincent Colaiuta","Pierre Habouzit","Todd Zullinger","Björn Steinbrink","Eric Schaefer","Junio C Hamano","Matthieu Moy","John Tapsell","René Scharfe","demerphq","Linus Torvalds","Dmitry Potapov","A Large Angry SCM"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"122778","messageId":"ef38762f0909091427m5b8f3am72c88fd4dbfebc59@mail.gmail.com","threadId":"20892","inReplyTo":null,"subject":"obnoxious CLI complaints","fromName":"Brendan Miller","fromEmail":"catphive@catphive.net","sentAt":"2009-09-09T21:27:56Z","receivedAt":"2009-09-09T21:27:56Z","isPatch":false,"sender":{"key":"catphive@catphive.net","avatar":"https://gravatar.com/avatar/d6048400272e913886f5ee25c1bca2020dc014547231c1dc148fdfa1631e31d3?d=mp&s=160"},"body":"Here are a bunch of really basic usability issues I have with git:\n\n1. cloning from a new empty repo fails, and so do a lot of other\noperations. This adds unnecessary steps to setting up a new shared\nrepo.\n\n2. git --bare init. The flag goes before the operation unlike every other flag?\n\n3. It's not obvious whether operations work on the working\ndirectory/the \"index\"/the repository\ne.g. get reset --soft, --mixed, --hard. git diff --cached\n\n4. The index is inconsistently referred to as too many different\nthings (cache, index, staging area) and only the last one makes any\nintuitive sense to a new user. This is partially a CLI issue, and\npartially a documentation issue, but both add up to cause confusion.\n\n5. Most commands require lots of flags, and don't have reasonable\ndefaults. e.g. archive.\n\ngit archive --format=tar --prefix=myproject/ HEAD | gzip >myproject.tar.gz\n\nShould just be:\ngit archive\nrun from the root of the repo.\n\nThis is what I want to do 90% of the time, so it should just have the\nproper defaults, and not make me look at the man page every time I\nwant to use it.\n\n6. Where is the bug tracker? If people users can't find the bug\ntracker, they can't report issues, and obnoxious bugs go unfixed, or\npeople have to whine on the mailing list. There should be a nice big\nlink on the front page of git-scm.com. A bug tracker is really the\nonly way for the vast majority of a community that use a tool can give\nfeedback on the problems the tool has.\n\n7. Man pages: It's nice we have them, but we shouldn't need them to do\nbasic stuff. I rarely had to look at the man pages using svn, but\nevery single time I use git I have to dig into these things. Frankly,\nI have better things to do than RTFM.\n\n8. There's no obvious way to make a remote your default push pull\nlocation without editing the git config file. Why not just something\nlike\n\ngit remote setdefault origin\n\nor even\n\ngit remote add --default origin http://somegiturl.org/\n\nThis come up in the use case where I:\n1. set up a remote bare repo\n2. push from my local repo, and thence forth want to keep local and\nremote in sink.\n\nRight now I have to modify .git/config to do this.\n\nIt's ok to have kind of a weak UI on a new tool, when people are busy\nadding basic functionality. However, at this point git already has way\nmore features than most of the competition, and the needless\ncomplexity of the CLI is the biggest issue in day to day use.\n\nBrendan\n"},{"id":"122780","messageId":"m3fxavvl5k.fsf@localhost.localdomain","threadId":"20892","inReplyTo":"ef38762f0909091427m5b8f3am72c88fd4dbfebc59@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-09-09T21:54:42Z","receivedAt":"2009-09-09T21:54:42Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Brendan Miller <catphive@catphive.net> writes:\n\n> Here are a bunch of really basic usability issues I have with git:\n\nFirst question: which git version do you use?\n \n> 1. cloning from a new empty repo fails, and so do a lot of other\n> operations. This adds unnecessary steps to setting up a new shared\n> repo.\n\nI think it works in modern git (where modern might mean 'master',\ni.e. not yet released version)\n\n> \n> 2. git --bare init. The flag goes before the operation unlike every\n> other flag?\n\n\"git init --bare\" works in fit version 1.6.4.2\n\nIn \"git --bare init\" the --bare option is to 'git' wrapper, not to\ngit-init command (see git(1)):\n\n  --bare Treat the repository as a bare repository. If GIT_DIR\n         environment is not set, it is set to the current working\n         directory.\n\n> \n> 3. It's not obvious whether operations work on the working\n> directory/the \"index\"/the repository\n> e.g. get reset --soft, --mixed, --hard. git diff --cached\n\nThere is \"git diff --staged\" synonym for \"git diff --cached\"\n\n> \n> 4. The index is inconsistently referred to as too many different\n> things (cache, index, staging area) and only the last one makes any\n> intuitive sense to a new user. This is partially a CLI issue, and\n> partially a documentation issue, but both add up to cause confusion.\n\nUsage of '--index' and '--cached' in CLI is consistent, and different.\nSee gitcli(7) manpage.\n\nSome of those inconsistences are historical remainings (I think we got\nrid of 'dircache' and 'ent').  Do you offer to do a cleanup?\n\n> \n> 5. Most commands require lots of flags, and don't have reasonable\n> defaults. e.g. archive.\n> \n> git archive --format=tar --prefix=myproject/ HEAD | gzip >myproject.tar.gz\n> \n> Should just be:\n> git archive\n> run from the root of the repo.\n\nI'd rather not have \"git archive\" work without specifying tree-ish.\nAs for having to do compression using separate program: do one thing\nand do it well is UNIX philosophy, and Git is UNIX-y tool.\n\nBTW. git-archive _has_ default format type (and empty prefix by\ndefault).\n\n> \n> This is what I want to do 90% of the time, so it should just have the\n> proper defaults, and not make me look at the man page every time I\n> want to use it.\n\nYou learn those idioms.\n\n> \n> 6. Where is the bug tracker? If people users can't find the bug\n> tracker, they can't report issues, and obnoxious bugs go unfixed, or\n> people have to whine on the mailing list. There should be a nice big\n> link on the front page of git-scm.com. A bug tracker is really the\n> only way for the vast majority of a community that use a tool can give\n> feedback on the problems the tool has.\n\nDo you offer to maintain and manage such bug tracker?  I mean here\ntaking care of duplicated bugs, tracking which bugs are resolved and\nwhich are not, checking if bug is reproductible, etc.  Do you?\nUnmaintained bugtracker is worse than useless.\n\nUsing mailing list for bug reports and for patches is time-honored\nworkflow, which works rather well for smaller projects such as Git.\nNote that git mailing list is free for all; you don't need to\nsubscribe to send, and you can watch it via many archives and gateways\n(like GMane).\n\n> \n> 7. Man pages: It's nice we have them, but we shouldn't need them to do\n> basic stuff. I rarely had to look at the man pages using svn, but\n> every single time I use git I have to dig into these things. Frankly,\n> I have better things to do than RTFM.\n\nLearn.  If you learn the philosophy behind git design, you would have\nmuch easier understanding and remembering git.\n\nThere is \"Git User's Manual\", \"The Git Community Book\", \"Pro Git\" and\nmany other references.\n\n> \n> 8. There's no obvious way to make a remote your default push pull\n> location without editing the git config file. Why not just something\n> like\n\norigin is default, I think.\n\n> \n> git remote setdefault origin\n> \n> or even\n> \n> git remote add --default origin http://somegiturl.org/\n> \n> This come up in the use case where I:\n> 1. set up a remote bare repo\n> 2. push from my local repo, and thence forth want to keep local and\n> remote in sink.\n> \n> Right now I have to modify .git/config to do this.\n\nAnd?\n\n> It's ok to have kind of a weak UI on a new tool, when people are busy\n> adding basic functionality. However, at this point git already has way\n> more features than most of the competition, and the needless\n> complexity of the CLI is the biggest issue in day to day use.\n\nCreating good UI is not easy, especially if you are limited by\nbackward compatibility.\n\n-- \nJakub Narebski\n\nGit User's Survey 2009: http://tinyurl.com/GitSurvey2009\n"},{"id":"122781","messageId":"fabb9a1e0909091458m1b2115a4g96e8fc47329257a2@mail.gmail.com","threadId":"20892","inReplyTo":"ef38762f0909091427m5b8f3am72c88fd4dbfebc59@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-09T21:58:32Z","receivedAt":"2009-09-09T21:58:32Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Wed, Sep 9, 2009 at 23:27, Brendan Miller<catphive@catphive.net> wrote:\n> 1. cloning from a new empty repo fails, and so do a lot of other\n> operations. This adds unnecessary steps to setting up a new shared\n> repo.\n\nActually, it works in recent git.\n\n> 2. git --bare init. The flag goes before the operation unlike every other flag?\n\nBecause unlike most flags it applies to anything git does, e.g. 'git\n--bare status' to treat the current directory as a git repository\nrather than looking for a .git directory.\n\n> 4. The index is inconsistently referred to as too many different\n> things (cache, index, staging area) and only the last one makes any\n> intuitive sense to a new user. This is partially a CLI issue, and\n> partially a documentation issue, but both add up to cause confusion.\n>\n> 5. Most commands require lots of flags, and don't have reasonable\n> defaults. e.g. archive.\n\nMost git commands need no more than two flags, and the defaults are\nreasonable to me; of course everybody has different needs, git\naliasses make it easy to overcome this.\n\n> This is what I want to do 90% of the time, so it should just have the\n> proper defaults, and not make me look at the man page every time I\n> want to use it.\n\nAgain, make an alias if you use it a lot; it might be what _you_ want\nto do, but as you can see from the plethora of other examples, it is\nperhaps not what everybody else wants to do 90% of the time.\n\n> 6. Where is the bug tracker? If people users can't find the bug\n> tracker, they can't report issues, and obnoxious bugs go unfixed, or\n> people have to whine on the mailing list. There should be a nice big\n> link on the front page of git-scm.com. A bug tracker is really the\n> only way for the vast majority of a community that use a tool can give\n> feedback on the problems the tool has.\n\nNope, that's not how things work for us. We _want_ people to 'whine'\non the mailing list, so that if they really don't care that much about\nsomething, it is \"dropped on the floor\" (because the thread becomes\nstale) after a while, and we move on. Bug trackers are notorious for\ngrowing in size very fast, and becoming cluttered (I have experience\nwith this as well, and am very pleased with how the git's mailing list\napproach solves this).\n\n> 7. Man pages: It's nice we have them, but we shouldn't need them to do\n> basic stuff. I rarely had to look at the man pages using svn, but\n> every single time I use git I have to dig into these things. Frankly,\n> I have better things to do than RTFM.\n\nHonestly, you never had to consult the help for svn? Perhaps the help\nwas not in a man page, but in some obscure website online; I for one\nwelcome our on-disk information bringing overlords.\n\n> 8. There's no obvious way to make a remote your default push pull\n> location without editing the git config file. Why not just something\n> like\n\n> It's ok to have kind of a weak UI on a new tool, when people are busy\n> adding basic functionality. However, at this point git already has way\n> more features than most of the competition, and the needless\n> complexity of the CLI is the biggest issue in day to day use.\n\nIf you don't need all that functionality, why not just use one of them\nfancy GUI's out there?\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"122783","messageId":"4C1FB36D-F8A6-4C01-A42A-8AD2355A9961@wincent.com","threadId":"20892","inReplyTo":"m3fxavvl5k.fsf@localhost.localdomain","subject":"Re: obnoxious CLI complaints","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2009-09-09T22:06:04Z","receivedAt":"2009-09-09T22:06:04Z","isPatch":false,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 09/09/2009, a las 23:54, Jakub Narebski escribió:\n\n> Brendan Miller <catphive@catphive.net> writes:\n>\n>> 5. Most commands require lots of flags, and don't have reasonable\n>> defaults. e.g. archive.\n>>\n>> git archive --format=tar --prefix=myproject/ HEAD | gzip  \n>> >myproject.tar.gz\n>>\n>> Should just be:\n>> git archive\n>> run from the root of the repo.\n>\n> I'd rather not have \"git archive\" work without specifying tree-ish.\n\nWhy, out of interest? I would've thought that HEAD would be a pretty  \ngood default, although I confess that I have never used \"git archive\"  \nwithout specifying a particular signed tag.\n\nCheers,\nWincent\n"},{"id":"122785","messageId":"20090909225820.GD29776@artemis.corp","threadId":"20892","inReplyTo":"ef38762f0909091427m5b8f3am72c88fd4dbfebc59@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Pierre Habouzit","fromEmail":"madcoder@madism.org","sentAt":"2009-09-09T22:58:21Z","receivedAt":"2009-09-09T22:58:21Z","isPatch":false,"sender":{"key":"madcoder@madism.org","avatar":null},"body":"On Wed, Sep 09, 2009 at 02:27:56PM -0700, Brendan Miller wrote:\n> 5. Most commands require lots of flags, and don't have reasonable\n> defaults. e.g. archive.\n> \n> git archive --format=tar --prefix=myproject/ HEAD | gzip >myproject.tar.gz\n> \n> Should just be:\n> git archive\n> run from the root of the repo.\n\nYou can't, because \"myproject\" cannot be guessed most of the time.\n\nIf you really want to automatize it, it's a 2 liner shell script, or\nalternatively you can add that to your .gitconfig:\n\n[alias]\n    archive-gz=!git archive --prefix=\"$(basename \"$(dirname \"$(readlink -m \"$(git rev-parse --git-dir)\")\")\")\"/ HEAD | gzip -c\n\nIt will use the name of the directory containing your .git/ directory as a\nprefix, and compress it using gzip to stdout.\n\ngit archive-gz > myproject.tar.gz will do what you want.\n\nSee, that's the point about git having so many flags. You only need to\nlook the man page _once_ (despite what you pretend): the one time you\nneed to write your convenient wrapper around git commands that suits\nyour exact needs.\n\n\n-- \n·O·  Pierre Habouzit\n··O                                                madcoder@debian.org\nOOO                                                http://www.madism.org\n"},{"id":"122787","messageId":"ef38762f0909091709t7336d86dkd2f175e5b3a6a3f@mail.gmail.com","threadId":"20892","inReplyTo":"m3fxavvl5k.fsf@localhost.localdomain","subject":"Re: obnoxious CLI complaints","fromName":"Brendan Miller","fromEmail":"catphive@catphive.net","sentAt":"2009-09-10T00:09:31Z","receivedAt":"2009-09-10T00:09:31Z","isPatch":false,"sender":{"key":"catphive@catphive.net","avatar":"https://gravatar.com/avatar/d6048400272e913886f5ee25c1bca2020dc014547231c1dc148fdfa1631e31d3?d=mp&s=160"},"body":"On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n> Brendan Miller <catphive@catphive.net> writes:\n> First question: which git version do you use?\n\nIt sounds like a bunch of things have been fixed in yet to be released\nversions. That's great.\n\n>>\n>> This is what I want to do 90% of the time, so it should just have the\n>> proper defaults, and not make me look at the man page every time I\n>> want to use it.\n>\n> You learn those idioms.\n\nI guess. Is that a good thing? Is the goal of interface design to make\nit difficult so I need to learn a lot of things, or easy so I can\nremain blissfully ignorant but still do what I want?\n\n>\n>>\n>> 6. Where is the bug tracker? If people users can't find the bug\n>> tracker, they can't report issues, and obnoxious bugs go unfixed, or\n>> people have to whine on the mailing list. There should be a nice big\n>> link on the front page of git-scm.com. A bug tracker is really the\n>> only way for the vast majority of a community that use a tool can give\n>> feedback on the problems the tool has.\n>\n> Do you offer to maintain and manage such bug tracker?  I mean here\n> taking care of duplicated bugs, tracking which bugs are resolved and\n> which are not, checking if bug is reproductible, etc.  Do you?\n> Unmaintained bugtracker is worse than useless.\n>\n> Using mailing list for bug reports and for patches is time-honored\n> workflow, which works rather well for smaller projects such as Git.\n> Note that git mailing list is free for all; you don't need to\n> subscribe to send, and you can watch it via many archives and gateways\n> (like GMane).\n\nBug trackers are a hassle, believe me, I know... but I think they\ncontribute to the overall quality of the product if used effectively.\nMailing lists seem like a good way to forget about bugs after people\nhave given up on getting developers to fix them.\n\n>\n>>\n>> 7. Man pages: It's nice we have them, but we shouldn't need them to do\n>> basic stuff. I rarely had to look at the man pages using svn, but\n>> every single time I use git I have to dig into these things. Frankly,\n>> I have better things to do than RTFM.\n>\n> Learn.  If you learn the philosophy behind git design, you would have\n> much easier understanding and remembering git.\n\nI think what you mean by philosophy is the underlying data structures,\nwhich are discussed in the manual (how many apps do you have that do\nthat!). I have read that. However, that one needs to understand\nunderlying data structure is just one more hurdle to understanding\ngit.\n\nIf I use GCC, do I need to know that it has a recursive descent\nparser? That it is implemented with a garbage collector? No. I just\nneed to know that I give it C, and it gives me a binary.\n\nExample:\ngcc main.c\n\nThink about all the defaults that are specified here! I don't\nexplicitly tell it how to find libc.so or what path the dynamic linker\nis at. I don't even really need to tell it which operation it is\nperforming, i.e. generating a binary, .o, .so, .os, .a, etc because it\nhas a smart default.\n\nThis an order of magnitude more complex than any git operation in\nterms of implementation, but it is dead simple from the users\nperspective.\n\n>\n> There is \"Git User's Manual\", \"The Git Community Book\", \"Pro Git\" and\n> many other references.\n\nYeah, I've been reading them. I'm saying that the docs are a crutch.\nRTFM is the problem not the solution. It makes the user do more work\nto avoid fixing usability issues.\n\nA CLI has some inherent limitations in that it doesn't have big\nlabeled buttons to press. However, that doesn't mean it has to be hard\nto use. I think a lot of the strength of the linux CLI is that most of\nthe utilities have actually pretty well thought out interfaces that\nhave been refined over time. That one's that aren't like that... well,\nno one uses them.\n\nI'm not saying that a unixy approach is wrong, but that most unix\nutilities are much easier to use than git, and that git needs\nimprovement on this front.\n\nBrendan\n"},{"id":"122789","messageId":"20090910012531.GU4297@inocybe.localdomain","threadId":"20892","inReplyTo":"ef38762f0909091709t7336d86dkd2f175e5b3a6a3f@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Todd Zullinger","fromEmail":"tmz@pobox.com","sentAt":"2009-09-10T01:25:32Z","receivedAt":"2009-09-10T01:25:32Z","isPatch":false,"sender":{"key":"tmz@pobox.com","avatar":"https://avatars.githubusercontent.com/u/806319?v=4"},"body":"Brendan Miller wrote:\n> On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n>> Brendan Miller <catphive@catphive.net> writes:\n>> First question: which git version do you use?\n>\n> It sounds like a bunch of things have been fixed in yet to be released\n> versions. That's great.\n\nIf I am not mistaken, support for cloning an empty repo was available\nin 1.6.2, which was released in March.\n\n-- \nTodd        OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nDrugs may lead to nowhere, but at least it's the scenic route.\n\n"},{"id":"122790","messageId":"20090910013235.GA9980@atjola.homenet","threadId":"20892","inReplyTo":"ef38762f0909091427m5b8f3am72c88fd4dbfebc59@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Björn Steinbrink","fromEmail":"b.steinbrink@gmx.de","sentAt":"2009-09-10T01:32:35Z","receivedAt":"2009-09-10T01:32:35Z","isPatch":false,"sender":{"key":"b.steinbrink@gmx.de","avatar":"https://avatars.githubusercontent.com/u/230962?v=4"},"body":"On 2009.09.09 14:27:56 -0700, Brendan Miller wrote:\n> 8. There's no obvious way to make a remote your default push pull\n> location without editing the git config file. Why not just something\n> like\n> \n> git remote setdefault origin\n\nBecause \"git remote\" is the wrong tool. The default remote for\nfetch/push is configured per branch head, not globally.\n\n> or even\n> \n> git remote add --default origin http://somegiturl.org/\n\nBecause that would likely mean changing all the existing branch head\nconfigurations, quite possibly making them invalid, because the\nbranch.<name>.merge value suddenly makes no sense anymore.\n\n> This come up in the use case where I:\n> 1. set up a remote bare repo\n> 2. push from my local repo, and thence forth want to keep local and\n> remote in sink.\n\nMaybe you want something like this?\nhttp://thread.gmane.org/gmane.comp.version-control.git/107671\n\n> Right now I have to modify .git/config to do this.\n\nYou can also do:\ngit config branch.<name>.remote <remote>\n\nwhich does the config editing for you.\n\nAnd maybe:\ngit config branch.<name>.merge <ref>\n\nif you also want just \"git pull\" to work, or use push.default = tracking.\n\n\nThere's also still my old \"retrack\" hack, which John Wiegley extended:\nhttp://github.com/jwiegley/git-scripts/blob/6ba3184d7b9f6dae3d10379a6bac29a01ceef190/git-retrack\n\nThat's a bit more comfortable, but probably doesn't work for a lot of\n\"non-standard\" setups.\n\nBjörn\n"},{"id":"122796","messageId":"200909101116.55098.jnareb@gmail.com","threadId":"20892","inReplyTo":"ef38762f0909091709t7336d86dkd2f175e5b3a6a3f@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-09-10T09:16:53Z","receivedAt":"2009-09-10T09:16:53Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Thu, 10 Sep 2009, Brendan Miller wrote:\n> On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n\n>> Brendan Miller <catphive@catphive.net> writes:\n>> First question: which git version do you use?\n> \n> It sounds like a bunch of things have been fixed in yet to be released\n> versions. That's great.\n\nBoth \"git init --bare\" and cloning empty repository are in _released_\nversions.\n \n>>> This is what I want to do 90% of the time, so it should just have the\n>>> proper defaults, and not make me look at the man page every time I\n>>> want to use it.\n>>\n>> You learn those idioms.\n> \n> I guess. Is that a good thing? Is the goal of interface design to make\n> it difficult so I need to learn a lot of things, or easy so I can\n> remain blissfully ignorant but still do what I want?\n\nThere are at least two issues:\n1. What you want to do 90% of time might be not what other people want\n   to do 90% of time.\n2. Some thing are due to git philosophy (like e.g. \"git commit -a\").\n \nAs to git-archive example: first, git-archive _has_ default format, and\nit is tar.  Second, compression is better left to separate program, but\nI guess we can follow GNU tar example and add equivalents of -Z/-z/-j\nand --use-compress-program options when using --output=<file>.  Third,\nwhen using e.g. tar you have to specify files to compress, so I don't\nknow why you complain that git-archive requires equivalent, HEAD in your\nexample.\n\n>>> 6. Where is the bug tracker? If people users can't find the bug\n>>> tracker, they can't report issues, and obnoxious bugs go unfixed, or\n>>> people have to whine on the mailing list. There should be a nice big\n>>> link on the front page of git-scm.com. A bug tracker is really the\n>>> only way for the vast majority of a community that use a tool can give\n>>> feedback on the problems the tool has.\n>>\n>> Do you offer to maintain and manage such bug tracker?  I mean here\n>> taking care of duplicated bugs, tracking which bugs are resolved and\n>> which are not, checking if bug is reproductible, etc.  Do you?\n>> Unmaintained bugtracker is worse than useless.\n>>\n>> Using mailing list for bug reports and for patches is time-honored\n>> workflow, which works rather well for smaller projects such as Git.\n>> Note that git mailing list is free for all; you don't need to\n>> subscribe to send, and you can watch it via many archives and gateways\n>> (like GMane).\n> \n> Bug trackers are a hassle, believe me, I know... but I think they\n> contribute to the overall quality of the product if used effectively.\n> Mailing lists seem like a good way to forget about bugs after people\n> have given up on getting developers to fix them.\n\nThis is a good way to separate important from unimportant bug reports\nand feature requests ;-)\n\n>>> 7. Man pages: It's nice we have them, but we shouldn't need them to do\n>>> basic stuff. I rarely had to look at the man pages using svn, but\n>>> every single time I use git I have to dig into these things. Frankly,\n>>> I have better things to do than RTFM.\n>>\n>> Learn.  If you learn the philosophy behind git design, you would have\n>> much easier understanding and remembering git.\n> \n> I think what you mean by philosophy is the underlying data structures,\n> which are discussed in the manual (how many apps do you have that do\n> that!). I have read that. However, that one needs to understand\n> underlying data structure is just one more hurdle to understanding\n> git.\n\nNo, I didn't mean understanding underlying data structures, but \nunderstanding philosophy: graph of revisions; tracking contents; refs\nas pointers to graph of revisions; the trifecta of working area, \nthe index and repository, etc.\n\n> If I use GCC, do I need to know that it has a recursive descent\n> parser? That it is implemented with a garbage collector? No. I just\n> need to know that I give it C, and it gives me a binary.\n\nBetter example would be using \"make\".  You need to understand 'make'\nphilosophy to write all but most simple of Makefiles.\n\n> \n> Example:\n> gcc main.c\n> \n> Think about all the defaults that are specified here! I don't\n> explicitly tell it how to find libc.so or what path the dynamic linker\n> is at. I don't even really need to tell it which operation it is\n> performing, i.e. generating a binary, .o, .so, .os, .a, etc because it\n> has a smart default.\n\nAnd if you are smart, you never use this form, but \"gcc -o main main.c\".\nAnd you have to specify '-lm' if you use math routines.  Not that simple,\nisn't it?\n\n> This an order of magnitude more complex than any git operation in\n> terms of implementation, but it is dead simple from the users\n> perspective.\n\nWhen git (or the concept of DVCS) is as old as gcc (or C compiler) is\nnow, then we can talk.\n \n>> There is \"Git User's Manual\", \"The Git Community Book\", \"Pro Git\" and\n>> many other references.\n> \n> Yeah, I've been reading them. I'm saying that the docs are a crutch.\n> RTFM is the problem not the solution. It makes the user do more work\n> to avoid fixing usability issues.\n\nWhen the tool is more complicated (like DVCS), you can't use it in all\nbut simplest cases without understanding it.\n\n> A CLI has some inherent limitations in that it doesn't have big\n> labeled buttons to press. However, that doesn't mean it has to be hard\n> to use. I think a lot of the strength of the linux CLI is that most of\n> the utilities have actually pretty well thought out interfaces that\n> have been refined over time. That one's that aren't like that... well,\n> no one uses them.\n> \n> I'm not saying that a unixy approach is wrong, but that most unix\n> utilities are much easier to use than git, and that git needs\n> improvement on this front.\n\nI'm not saying that git doesn't need UI (and documentation) improvements.\nBut first, your attitude is a bit grating, and second, your examples\nare not it.\n\nOn the other hand there is inherent problems that serious git \ncontributors use git for a long time and are used to (and perhaps even\nattached to) git UI warts, and newbies which start to use git not always\ncan distinguish between things that can be changed and things that cannot\nbe changed.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"122821","messageId":"200909101850.26109.jnareb@gmail.com","threadId":"20892","inReplyTo":"4C1FB36D-F8A6-4C01-A42A-8AD2355A9961@wincent.com","subject":"Re: obnoxious CLI complaints","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-09-10T16:50:24Z","receivedAt":"2009-09-10T16:50:24Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia czwartek 10. września 2009 00:06, Wincent Colaiuta napisał:\n> El 09/09/2009, a las 23:54, Jakub Narebski escribió:\n>> Brendan Miller <catphive@catphive.net> writes:\n>>\n>>> 5. Most commands require lots of flags, and don't have reasonable\n>>> defaults. e.g. archive.\n>>>\n>>> $ git archive --format=tar --prefix=myproject/ HEAD | \n>>> > gzip myproject.tar.gz \n>>>\n>>> Should just be:\n>>> git archive\n>>> run from the root of the repo.\n>>\n>> I'd rather not have \"git archive\" work without specifying tree-ish.\n> \n> Why, out of interest? I would've thought that HEAD would be a pretty  \n> good default, although I confess that I have never used \"git archive\"  \n> without specifying a particular signed tag.\n\nFirst, it would be consistent with how ordinary archivers such as tar\nor zip are used, where you have to specify list of files to archive\n(in our case this list is HEAD).  Second, I'd rather not accidentally\ndump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\noutput.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"122824","messageId":"34f8975d0909101118x7c95be1ehda085bea1611b70c@mail.gmail.com","threadId":"20892","inReplyTo":"200909101116.55098.jnareb@gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Eric Schaefer","fromEmail":"eric.schaefer@ericschaefer.org","sentAt":"2009-09-10T18:18:14Z","receivedAt":"2009-09-10T18:18:14Z","isPatch":false,"sender":{"key":"eric.schaefer@ericschaefer.org","avatar":"https://gravatar.com/avatar/1a2639f5b7e8143f5569c2818ee363d9023c4b75cd0ddfb843b00a951a439c26?d=mp&s=160"},"body":"2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n> This is a good way to separate important from unimportant bug reports\n> and feature requests ;-)\n\n\"Unimportant bug reports\"? Interesting concept... ;-)\n\nBTW: A bug tracker has the advantage that bugs don't fall on the\nfloor. They can be postponed for later fixing but you will not forget\nthem.\nBut you are right about feature request. You would either have to have\na rigorous policy of dropping bogus or unwanted (unimportant) requests\nor you go with the mailing list approach to keep the pile from\nstinking. ;-)\n\nEric\n"},{"id":"122828","messageId":"fabb9a1e0909101152n4d55b344p60da1529fa58eb01@mail.gmail.com","threadId":"20892","inReplyTo":"34f8975d0909101118x7c95be1ehda085bea1611b70c@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-10T18:52:08Z","receivedAt":"2009-09-10T18:52:08Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Thu, Sep 10, 2009 at 20:18, Eric Schaefer\n<eric.schaefer@ericschaefer.org> wrote:\n> \"Unimportant bug reports\"? Interesting concept... ;-)\n\nSure, if there's a bug in feature foo, but it only happens when\ninvoking it with some rarely used argument, and only on Solaris\nplatforms, it is probably not worth spending time on it if the\noriginal reporter does not even have the time to stick around and aid\nin resolving the issue. It's probably better to spend that precious\ntime on other bug fixes, or features instead.\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"122829","messageId":"7vbpliaaxo.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"200909101850.26109.jnareb@gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-10T18:53:23Z","receivedAt":"2009-09-10T18:53:23Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> First, it would be consistent with how ordinary archivers such as tar\n> or zip are used, where you have to specify list of files to archive\n> (in our case this list is HEAD).  Second, I'd rather not accidentally\n> dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n> output.\n\nSo does \"cat\".  I do not agree with your second point.\n\nWhile I somewhat see the similarity argument, your first point, I am not\nsure if it is relevant.  It is not like \"tar or zip allows us to say what\nfiles to archive, but git-archive doesn't and it always archives HEAD\";\nyou are saying \"they require us to specify, so should we\".\n\nBut I do not see a strong reason not to default to HEAD.  The case that\nwould make difference would be to differentiate among\n\n\t$ git archive HEAD TAIL\n        $ git archive HEAD -- TAIL\n        $ git archive -- HEAD TAIL\n\ni.e. what if you happen to have a tracked content called HEAD.  I didn't\ncheck the current command line parser in git-archive understands the \"--\"\nconvention for that, but it is not a rocket science to add it if it\ndoesn't.\n"},{"id":"122830","messageId":"vpqtyzabpgm.fsf@bauges.imag.fr","threadId":"20892","inReplyTo":"20090910013235.GA9980@atjola.homenet","subject":"Re: obnoxious CLI complaints","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2009-09-10T18:54:17Z","receivedAt":"2009-09-10T18:54:17Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Björn Steinbrink <B.Steinbrink@gmx.de> writes:\n\n> On 2009.09.09 14:27:56 -0700, Brendan Miller wrote:\n>> 8. There's no obvious way to make a remote your default push pull\n>> location without editing the git config file. Why not just something\n>> like\n>> \n>> git remote setdefault origin\n>\n> Because \"git remote\" is the wrong tool. The default remote for\n> fetch/push is configured per branch head, not globally.\n\n(the --track option of git branch and git checkout can help).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"122832","messageId":"43d8ce650909101246l50189c97r4f3fc4a8d7a0bd4@mail.gmail.com","threadId":"20892","inReplyTo":"200909101850.26109.jnareb@gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-09-10T19:46:58Z","receivedAt":"2009-09-10T19:46:58Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n> Dnia czwartek 10. września 2009 00:06, Wincent Colaiuta napisał:\n>> El 09/09/2009, a las 23:54, Jakub Narebski escribió:\n>>> Brendan Miller <catphive@catphive.net> writes:\n>>>\n>>>> 5. Most commands require lots of flags, and don't have reasonable\n>>>> defaults. e.g. archive.\n>>>>\n>>>> $ git archive --format=tar --prefix=myproject/ HEAD |\n>>>> > gzip myproject.tar.gz\n>>>>\n>>>> Should just be:\n>>>> git archive\n>>>> run from the root of the repo.\n>>>\n>>> I'd rather not have \"git archive\" work without specifying tree-ish.\n>>\n>> Why, out of interest? I would've thought that HEAD would be a pretty\n>> good default, although I confess that I have never used \"git archive\"\n>> without specifying a particular signed tag.\n>\n> First, it would be consistent with how ordinary archivers such as tar\n> or zip are used, where you have to specify list of files to archive\n> (in our case this list is HEAD).  Second, I'd rather not accidentally\n> dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n> output.\n\nThat could be fixed by outputting to a file.  git format-patch outputs\nto a file, so why wouldn't git achieve?\n\nJohn\n"},{"id":"122834","messageId":"fabb9a1e0909101317t4cbfc582k641a64a806ed8dcc@mail.gmail.com","threadId":"20892","inReplyTo":"43d8ce650909101246l50189c97r4f3fc4a8d7a0bd4@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-10T20:17:54Z","receivedAt":"2009-09-10T20:17:54Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Thu, Sep 10, 2009 at 21:46, John Tapsell <johnflux@gmail.com> wrote:\n> That could be fixed by outputting to a file.  git format-patch outputs\n> to a file, so why wouldn't git achieve?\n\nBecause git format-patch works on a per-patch basis, and patches\ninherently have a 'name' (the first line of the commit message), an\nentire repository does not, so one would have to resort to arbitrary\nnames such as 'archive.tar.gz' or such.\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"122835","messageId":"200909102223.31602.jnareb@gmail.com","threadId":"20892","inReplyTo":"43d8ce650909101246l50189c97r4f3fc4a8d7a0bd4@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-09-10T20:23:29Z","receivedAt":"2009-09-10T20:23:29Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:\n> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n\n> > First, it would be consistent with how ordinary archivers such as tar\n> > or zip are used, where you have to specify list of files to archive\n> > (in our case this list is HEAD).  Second, I'd rather not accidentally\n> > dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n> > output.\n> \n> That could be fixed by outputting to a file.  git format-patch outputs\n> to a file, so why wouldn't git achieve?\n\n\"git format-patch\" outputs to files because it generates _multiple_\nfiles; generating single patch is special case.  Also git-format-patch\ncan generate file names from patch (commit) subject; it is not the case\nfor \"git archive\" (what name should it use?).\n\n-- \nJakub Narebski\nPoland\n"},{"id":"122847","messageId":"43d8ce650909101504q32448cb9w562a43969d01b1fe@mail.gmail.com","threadId":"20892","inReplyTo":"200909102223.31602.jnareb@gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-09-10T22:04:05Z","receivedAt":"2009-09-10T22:04:05Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n> Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:\n>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>\n>> > First, it would be consistent with how ordinary archivers such as tar\n>> > or zip are used, where you have to specify list of files to archive\n>> > (in our case this list is HEAD).  Second, I'd rather not accidentally\n>> > dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n>> > output.\n>>\n>> That could be fixed by outputting to a file.  git format-patch outputs\n>> to a file, so why wouldn't git achieve?\n>\n> \"git format-patch\" outputs to files because it generates _multiple_\n> files; generating single patch is special case.  Also git-format-patch\n> can generate file names from patch (commit) subject; it is not the case\n> for \"git archive\" (what name should it use?).\n\nWhat if it used the current (or topleve) directory name?  Wouldn't\nthat work in most cases?  For cases it doesn't work, the user can just\nrename or specify the output name, so it would be no worse than the\ncurrent case.\n\nJohn\n"},{"id":"122849","messageId":"4AA97B59.9030903@lsrfire.ath.cx","threadId":"20892","inReplyTo":"7vbpliaaxo.fsf@alter.siamese.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-09-10T22:19:05Z","receivedAt":"2009-09-10T22:19:05Z","isPatch":false,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Junio C Hamano schrieb:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> First, it would be consistent with how ordinary archivers such as tar\n>> or zip are used, where you have to specify list of files to archive\n>> (in our case this list is HEAD).  Second, I'd rather not accidentally\n>> dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n>> output.\n> \n> So does \"cat\".  I do not agree with your second point.\n> \n> While I somewhat see the similarity argument, your first point, I am not\n> sure if it is relevant.  It is not like \"tar or zip allows us to say what\n> files to archive, but git-archive doesn't and it always archives HEAD\";\n> you are saying \"they require us to specify, so should we\".\n> \n> But I do not see a strong reason not to default to HEAD.  The case that\n> would make difference would be to differentiate among\n> \n> \t$ git archive HEAD TAIL\n>         $ git archive HEAD -- TAIL\n>         $ git archive -- HEAD TAIL\n> \n> i.e. what if you happen to have a tracked content called HEAD.  I didn't\n> check the current command line parser in git-archive understands the \"--\"\n> convention for that, but it is not a rocket science to add it if it\n> doesn't.\n\nCurrently it doesn't.  An attempt to implement it is below (tests and\ndocumentation update missing).\n\nI wonder if we want to make treeless calls to archive the worktree (or the\nindex) instead of HEAD, similar to git grep, though.  Not that I remember\nsomeone requesting such a thing, but I'm already slightly surprised about\narchive being used to tar up HEAD in any case -- I imagined it would mostly\nbe used to make releases of tagged versions.\n\n---\n archive.c |   34 ++++++++++++++++++++++++----------\n 1 files changed, 24 insertions(+), 10 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 0bca9ca..04fa6a5 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -214,18 +214,32 @@ static void parse_pathspec_arg(const char **pathspec,\n \tar_args->pathspec = get_pathspec(ar_args->base, pathspec);\n }\n \n-static void parse_treeish_arg(const char **argv,\n-\t\tstruct archiver_args *ar_args, const char *prefix)\n+static int parse_treeish_arg(int argc, const char **argv,\n+\t\t\t     struct archiver_args *ar_args, const char *prefix)\n {\n-\tconst char *name = argv[0];\n+\tconst char *name = \"HEAD\";\n \tconst unsigned char *commit_sha1;\n \ttime_t archive_time;\n \tstruct tree *tree;\n \tconst struct commit *commit;\n \tunsigned char sha1[20];\n \n+\tif (argc > 0) {\n+\t\tint consume = 1;\n+\n+\t\tif (strcmp(argv[0], \"--\")) {\n+\t\t\tname = argv[0];\n+\t\t\tif (argc > 1 && !strcmp(argv[1], \"--\"))\n+\t\t\t\tconsume++;\n+\t\t}\n+\n+\t\targc -= consume;\n+\t\tmemmove(argv, argv + consume, argc * sizeof(*argv));\n+\t\targv[argc] = NULL;\n+\t}\n+\n \tif (get_sha1(name, sha1))\n-\t\tdie(\"Not a valid object name\");\n+\t\tdie(\"Not a valid object name: %s\", name);\n \n \tcommit = lookup_commit_reference_gently(sha1, 1);\n \tif (commit) {\n@@ -256,6 +270,8 @@ static void parse_treeish_arg(const char **argv,\n \tar_args->commit_sha1 = commit_sha1;\n \tar_args->commit = commit;\n \tar_args->time = archive_time;\n+\n+\treturn argc;\n }\n \n #define OPT__COMPR(s, v, h, p) \\\n@@ -309,7 +325,8 @@ static int parse_archive_args(int argc, const char **argv,\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, NULL, opts, archive_usage, 0);\n+\targc = parse_options(argc, argv, NULL, opts, archive_usage,\n+\t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n \tif (remote)\n \t\tdie(\"Unexpected option --remote\");\n@@ -327,9 +344,6 @@ static int parse_archive_args(int argc, const char **argv,\n \t\texit(0);\n \t}\n \n-\t/* We need at least one parameter -- tree-ish */\n-\tif (argc < 1)\n-\t\tusage_with_options(archive_usage, opts);\n \t*ar = lookup_archiver(format);\n \tif (!*ar)\n \t\tdie(\"Unknown archive format '%s'\", format);\n@@ -361,8 +375,8 @@ int write_archive(int argc, const char **argv, const char *prefix,\n \tif (setup_prefix && prefix == NULL)\n \t\tprefix = setup_git_directory();\n \n-\tparse_treeish_arg(argv, &args, prefix);\n-\tparse_pathspec_arg(argv + 1, &args);\n+\targc = parse_treeish_arg(argc, argv, &args, prefix);\n+\tparse_pathspec_arg(argv, &args);\n \n \tgit_config(git_default_config, NULL);\n \n-- \n1.6.5.rc0\n"},{"id":"122850","messageId":"4AA97B61.6030301@lsrfire.ath.cx","threadId":"20892","inReplyTo":"200909101116.55098.jnareb@gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-09-10T22:19:13Z","receivedAt":"2009-09-10T22:19:13Z","isPatch":false,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Jakub Narebski schrieb:\n> [...] Second, compression is better left to separate program, but\n> I guess we can follow GNU tar example and add equivalents of -Z/-z/-j\n> and --use-compress-program options when using --output=<file>. [...]\n\nCompression only makes sense for the tar format, so I think it's better\nexposed by new formats and not by generic options.\n\nFor compress and bzip2 we'd need to call the external archiver, similar\nto a pager.  Interesting idea.\n\nFor gzip, we can use the zlib helper functions, since we're linking\nagainst it anyway.  I mention this because the following patch has been\nlaying around here for a while, collecting dust because it was a feature\nwaiting for a requester.\n\nUsing zlib directly avoids the overhead of a pipe and of buffering the\noutput for blocked writes; surprisingly (to me), it isn't any faster.\nI didn't make any tuning efforts, yet, though.  Anyway, here it is:\n\n---\n Documentation/git-archive.txt |    2 +-\n archive-tar.c                 |   76 ++++++++++++++++++++++++++++++++++++----\n archive.c                     |   43 ++++++++++++++++++++++-\n archive.h                     |    1 +\n t/t5000-tar-tree.sh           |   30 ++++++++++++++++\n 5 files changed, 141 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\nindex 92444dd..2935246 100644\n--- a/Documentation/git-archive.txt\n+++ b/Documentation/git-archive.txt\n@@ -34,7 +34,7 @@ OPTIONS\n -------\n \n --format=<fmt>::\n-\tFormat of the resulting archive: 'tar' or 'zip'.  The default\n+\tFormat of the resulting archive: 'tar', 'tar.gz' or 'zip'.  The default\n \tis 'tar'.\n \n -l::\ndiff --git a/archive-tar.c b/archive-tar.c\nindex cee06ce..f22304d 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -58,18 +58,78 @@ static void write_blocked(const void *data, unsigned long size)\n \twrite_if_needed();\n }\n \n+static void gzwrite_or_die(gzFile *gzfile, const void *buf, size_t count)\n+{\n+\tconst int chunk = 1 << 30; /* Big arbitrary value that fits into int. */\n+\tconst char *p = buf;\n+\n+\twhile (count > 0) {\n+\t\tunsigned int to_write = (count < chunk) ? count : chunk;\n+\t\tint written = gzwrite(gzfile, p, to_write);\n+\t\tif (written <= 0) {\n+\t\t\tint err;\n+\t\t\tconst char *msg = gzerror(gzfile, &err);\n+\t\t\tif (err != Z_ERRNO)\n+\t\t\t\tdie(\"zlib error: %s\", msg);\n+\t\t\tif (errno == EAGAIN || errno == EINTR)\n+\t\t\t\tcontinue;\n+\t\t\tif (errno == EPIPE)\n+\t\t\t\texit(0);\n+\t\t\tdie_errno(\"write error\");\n+\t\t}\n+\t\tcount -= written;\n+\t\tp += written;\n+\t}\n+}\n+\n+/*\n+ * Writes directly through zlib and pads with NUL bytes to multiples of\n+ * RECORDSIZE.  Updates offset because the length of the trailer depends\n+ * on it.\n+ */\n+static void write_to_tgz(struct archiver_args *args, const void *data,\n+\t\t\t unsigned long size)\n+{\n+\tunsigned long tail = size % RECORDSIZE;\n+\tgzwrite_or_die(args->gzfile, data, size);\n+\tif (tail) {\n+\t\ttail = RECORDSIZE - tail;\n+\t\tif (gzseek(args->gzfile, tail, SEEK_CUR) == -1)\n+\t\t\tdie(\"zlib error while seeking.\");\n+\t}\n+\toffset = (offset + size + tail) % BLOCKSIZE;\n+}\n+\n+static void write_to_archive(struct archiver_args *args, const void *data,\n+\t\t\t     unsigned long size)\n+{\n+\tif (args->gzfile)\n+\t\twrite_to_tgz(args, data, size);\n+\telse\n+\t\twrite_blocked(data, size);\n+}\n+\n /*\n  * The end of tar archives is marked by 2*512 nul bytes and after that\n  * follows the rest of the block (if any).\n  */\n-static void write_trailer(void)\n+static void write_trailer(struct archiver_args *args)\n {\n \tint tail = BLOCKSIZE - offset;\n-\tmemset(block + offset, 0, tail);\n-\twrite_or_die(1, block, BLOCKSIZE);\n-\tif (tail < 2 * RECORDSIZE) {\n-\t\tmemset(block, 0, offset);\n+\tif (args->gzfile) {\n+\t\tif (tail < 2 * RECORDSIZE)\n+\t\t\ttail += BLOCKSIZE;\n+\t\tif (gzseek(args->gzfile, tail - 1, SEEK_CUR) == -1)\n+\t\t\tdie(\"zlib error while seeking.\");\n+\t\tif (gzputc(args->gzfile, '\\0') == -1)\n+\t\t\tdie(\"zlib error while writing a NUL byte.\");\n+\t} else {\n+\t\tmemset(block + offset, 0, tail);\n \t\twrite_or_die(1, block, BLOCKSIZE);\n+\t\tif (tail < 2 * RECORDSIZE) {\n+\t\t\tmemset(block, 0, offset);\n+\t\t\twrite_or_die(1, block, BLOCKSIZE);\n+\t\t}\n \t}\n }\n \n@@ -201,9 +261,9 @@ static int write_tar_entry(struct archiver_args *args,\n \t\t\treturn err;\n \t}\n \tstrbuf_release(&ext_header);\n-\twrite_blocked(&header, sizeof(header));\n+\twrite_to_archive(args, &header, sizeof(header));\n \tif (S_ISREG(mode) && buffer && size > 0)\n-\t\twrite_blocked(buffer, size);\n+\t\twrite_to_archive(args, buffer, size);\n \treturn err;\n }\n \n@@ -245,6 +305,6 @@ int write_tar_archive(struct archiver_args *args)\n \tif (!err)\n \t\terr = write_archive_entries(args, write_tar_entry);\n \tif (!err)\n-\t\twrite_trailer();\n+\t\twrite_trailer(args);\n \treturn err;\n }\ndiff --git a/archive.c b/archive.c\nindex 0bca9ca..8809f51 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -15,6 +15,8 @@ static char const * const archive_usage[] = {\n };\n \n #define USES_ZLIB_COMPRESSION 1\n+#define USES_GZIP_COMPRESSION 2\n+#define USES_COMPRESSION (USES_ZLIB_COMPRESSION | USES_GZIP_COMPRESSION)\n \n static const struct archiver {\n \tconst char *name;\n@@ -22,6 +24,7 @@ static const struct archiver {\n \tunsigned int flags;\n } archivers[] = {\n \t{ \"tar\", write_tar_archive },\n+\t{ \"tar.gz\", write_tar_archive, USES_GZIP_COMPRESSION },\n \t{ \"zip\", write_zip_archive, USES_ZLIB_COMPRESSION },\n };\n \n@@ -336,7 +339,7 @@ static int parse_archive_args(int argc, const char **argv,\n \n \targs->compression_level = Z_DEFAULT_COMPRESSION;\n \tif (compression_level != -1) {\n-\t\tif ((*ar)->flags & USES_ZLIB_COMPRESSION)\n+\t\tif ((*ar)->flags & USES_COMPRESSION)\n \t\t\targs->compression_level = compression_level;\n \t\telse {\n \t\t\tdie(\"Argument not supported for format '%s': -%d\",\n@@ -351,11 +354,38 @@ static int parse_archive_args(int argc, const char **argv,\n \treturn argc;\n }\n \n+static void archive_gzfile_open(struct archiver_args *args)\n+{\n+\tchar mode[] = \"wbX\";\n+\tif (args->compression_level == Z_DEFAULT_COMPRESSION)\n+\t\tmode[2] = '\\0';\n+\telse\n+\t\tmode[2] = '0' + args->compression_level;\n+\targs->gzfile = gzdopen(xdup(1), mode);\n+\tif (!args->gzfile)\n+\t\tdie(\"zlib error: out of memory.\");\n+}\n+\n+static void archive_gzfile_close(struct archiver_args *args)\n+{\n+\tint err = gzclose(args->gzfile);\n+\tswitch (err) {\n+\tcase Z_OK:\n+\t\tbreak;\n+\tcase Z_ERRNO:\n+\t\tdie_errno(\"zlib error\");\n+\tdefault:\n+\t\tdie(\"zlib error %d while closing.\", err);\n+\t}\n+\targs->gzfile = NULL;\n+}\n+\n int write_archive(int argc, const char **argv, const char *prefix,\n \t\tint setup_prefix)\n {\n \tconst struct archiver *ar = NULL;\n \tstruct archiver_args args;\n+\tint err;\n \n \targc = parse_archive_args(argc, argv, &ar, &args);\n \tif (setup_prefix && prefix == NULL)\n@@ -366,5 +396,14 @@ int write_archive(int argc, const char **argv, const char *prefix,\n \n \tgit_config(git_default_config, NULL);\n \n-\treturn ar->write_archive(&args);\n+\targs.gzfile = NULL;\n+\tif (ar->flags & USES_GZIP_COMPRESSION)\n+\t\tarchive_gzfile_open(&args);\n+\n+\terr = ar->write_archive(&args);\n+\n+\tif (!err && (ar->flags & USES_GZIP_COMPRESSION))\n+\t\tarchive_gzfile_close(&args);\n+\n+\treturn err;\n }\ndiff --git a/archive.h b/archive.h\nindex 038ac35..638a7ba 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -12,6 +12,7 @@ struct archiver_args {\n \tunsigned int verbose : 1;\n \tunsigned int worktree_attributes : 1;\n \tint compression_level;\n+\tgzFile gzfile;\n };\n \n typedef int (*write_archive_fn_t)(struct archiver_args *);\ndiff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh\nindex 5f84b18..4094c18 100755\n--- a/t/t5000-tar-tree.sh\n+++ b/t/t5000-tar-tree.sh\n@@ -26,6 +26,8 @@ commit id embedding:\n \n . ./test-lib.sh\n UNZIP=${UNZIP:-unzip}\n+GZIP=${GZIP:-gzip}\n+GUNZIP=${GUNZIP:-$GZIP -d}\n \n SUBSTFORMAT=%H%n\n \n@@ -79,6 +81,15 @@ test_expect_success \\\n     'git tar-tree HEAD >b2.tar'\n \n test_expect_success \\\n+    'git archive --format=tar.gz' \\\n+    'git archive --format=tar.gz HEAD >bz.tar.gz'\n+\n+test_expect_success \\\n+    'git archive --format=tar.gz with --output' \\\n+    'git archive --format=tar.gz --output=bz1.tar.gz HEAD &&\n+     test_cmp bz.tar.gz bz1.tar.gz'\n+\n+test_expect_success \\\n     'git archive vs. git tar-tree' \\\n     'test_cmp b.tar b2.tar'\n \n@@ -146,7 +157,9 @@ test_expect_success \\\n     'cp .git/info/attributes .git/info/attributes.before &&\n      echo \"substfile?\" export-subst >>.git/info/attributes &&\n      git archive HEAD >f.tar &&\n+     git archive --format=tar.gz HEAD >fz.tar.gz &&\n      git archive --prefix=prefix/ HEAD >g.tar &&\n+     git archive --format=tar.gz --prefix=prefix/ HEAD >gz.tar.gz &&\n      mv .git/info/attributes.before .git/info/attributes'\n \n test_expect_success \\\n@@ -173,6 +186,23 @@ test_expect_success \\\n       test_cmp a/substfile2 g/prefix/a/substfile2\n '\n \n+$GUNZIP -h >/dev/null 2>&1\n+if [ $? -eq 127 ]; then\n+\techo \"Skipping tar.gz expansion tests, because gunzip was not found\"\n+else\n+\ttest_expect_success \\\n+\t\t'expand *.tar.gz' \\\n+\t\t'$GUNZIP bz.tar.gz &&\n+\t\t $GUNZIP fz.tar.gz &&\n+\t\t $GUNZIP gz.tar.gz'\n+\n+\ttest_expect_success \\\n+\t\t'compare files created by formats tar and tar.gz' \\\n+\t\t'test_cmp b.tar bz.tar &&\n+\t\t test_cmp f.tar fz.tar &&\n+\t\t test_cmp g.tar gz.tar'\n+fi\n+\n test_expect_success \\\n     'git archive --format=zip' \\\n     'git archive --format=zip HEAD >d.zip'\n-- \n1.6.5.rc0\n"},{"id":"122852","messageId":"7v4ora76vr.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"43d8ce650909101504q32448cb9w562a43969d01b1fe@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-10T22:49:12Z","receivedAt":"2009-09-10T22:49:12Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Tapsell <johnflux@gmail.com> writes:\n\n> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>> Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:\n>>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>>\n>>> > First, it would be consistent with how ordinary archivers such as tar\n>>> > or zip are used, where you have to specify list of files to archive\n>>> > (in our case this list is HEAD).  Second, I'd rather not accidentally\n>>> > dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n>>> > output.\n>>>\n>>> That could be fixed by outputting to a file.  git format-patch outputs\n>>> to a file, so why wouldn't git achieve?\n>>\n>> \"git format-patch\" outputs to files because it generates _multiple_\n>> files; generating single patch is special case.  Also git-format-patch\n>> can generate file names from patch (commit) subject; it is not the case\n>> for \"git archive\" (what name should it use?).\n>\n> What if it used the current (or topleve) directory name?  Wouldn't\n> that work in most cases?\n\nFollowing along the same line of reasoning, it would work in most cases if\nthe output is literally named \"archive.tar\".  If it is not the name the\nuser wants, the user can \"mv\" afterwards, or give an explicit filename.\n\nWhat it does _not_ allow is to send the output to a downstream command for\npostprocessing without introducing some magic token to say \"standard\noutput\" (e.g. \"git archive -f - | (cd ../foo && tar xf -)\").\n\nIf the default is to write to the standard output, we won't have all of\nthese issues.  People who want a file can name the file by\n\n\tgit archive >my.file.tar\n\nand people who want to pipe (which is 99% of the use pattern for me) can\nsay\n\n\tgit archive | down stream commands.\n\nOh, wait.\n\nThat is exactly what we have, so what's the point of continuing this\ndiscussion any further?  Can we just stop?\n"},{"id":"122853","messageId":"9b18b3110909101619n6904a75dm10dd0b5717fb0d76@mail.gmail.com","threadId":"20892","inReplyTo":"7v4ora76vr.fsf@alter.siamese.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"demerphq","fromEmail":"demerphq@gmail.com","sentAt":"2009-09-10T23:19:28Z","receivedAt":"2009-09-10T23:19:28Z","isPatch":false,"sender":{"key":"demerphq@gmail.com","avatar":null},"body":"2009/9/11 Junio C Hamano <gitster@pobox.com>:\n> John Tapsell <johnflux@gmail.com> writes:\n>\n>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>>> Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:\n>>>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>>>\n>>>> > First, it would be consistent with how ordinary archivers such as tar\n>>>> > or zip are used, where you have to specify list of files to archive\n>>>> > (in our case this list is HEAD).  Second, I'd rather not accidentally\n>>>> > dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n>>>> > output.\n>>>>\n>>>> That could be fixed by outputting to a file.  git format-patch outputs\n>>>> to a file, so why wouldn't git achieve?\n>>>\n>>> \"git format-patch\" outputs to files because it generates _multiple_\n>>> files; generating single patch is special case.  Also git-format-patch\n>>> can generate file names from patch (commit) subject; it is not the case\n>>> for \"git archive\" (what name should it use?).\n>>\n>> What if it used the current (or topleve) directory name?  Wouldn't\n>> that work in most cases?\n>\n> Following along the same line of reasoning, it would work in most cases if\n> the output is literally named \"archive.tar\".  If it is not the name the\n> user wants, the user can \"mv\" afterwards, or give an explicit filename.\n\nWhy not $sha1.tar?\n\n> What it does _not_ allow is to send the output to a downstream command for\n> postprocessing without introducing some magic token to say \"standard\n> output\" (e.g. \"git archive -f - | (cd ../foo && tar xf -)\").\n>\n> If the default is to write to the standard output, we won't have all of\n> these issues.  People who want a file can name the file by\n>\n>        git archive >my.file.tar\n>\n> and people who want to pipe (which is 99% of the use pattern for me) can\n> say\n>\n>        git archive | down stream commands.\n>\n> Oh, wait.\n>\n> That is exactly what we have, so what's the point of continuing this\n> discussion any further?  Can we just stop?\n\nIs it portable to assume that piping is always in binmode? From a\nportability POV i could imagine piping being a problem in this\nrespect, and might be why tar provides a way to output to a file and\nnot just to a handle. For example ISTR that on windows piping is by\ndefault in text mode. I think its not a showstopper there as you can\nchange it, but still, from a portability point of view you might not\nwant to depend on piping.\n\ncheers,\nYves\n\n\n-- \nperl -Mre=debug -e \"/just|another|perl|hacker/\"\n"},{"id":"122858","messageId":"43d8ce650909101718j2f1f77cbgc347ee755145353f@mail.gmail.com","threadId":"20892","inReplyTo":"7v4ora76vr.fsf@alter.siamese.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-09-11T00:18:55Z","receivedAt":"2009-09-11T00:18:55Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/9/11 Junio C Hamano <gitster@pobox.com>:\n> John Tapsell <johnflux@gmail.com> writes:\n>\n>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>>> Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:\n>>>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>>>\n>>>> > First, it would be consistent with how ordinary archivers such as tar\n>>>> > or zip are used, where you have to specify list of files to archive\n>>>> > (in our case this list is HEAD).  Second, I'd rather not accidentally\n>>>> > dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n>>>> > output.\n>>>>\n>>>> That could be fixed by outputting to a file.  git format-patch outputs\n>>>> to a file, so why wouldn't git achieve?\n>>>\n>>> \"git format-patch\" outputs to files because it generates _multiple_\n>>> files; generating single patch is special case.  Also git-format-patch\n>>> can generate file names from patch (commit) subject; it is not the case\n>>> for \"git archive\" (what name should it use?).\n>>\n>> What if it used the current (or topleve) directory name?  Wouldn't\n>> that work in most cases?\n>\n> Following along the same line of reasoning, it would work in most cases if\n> the output is literally named \"archive.tar\".  If it is not the name the\n> user wants, the user can \"mv\" afterwards, or give an explicit filename.\n\nThat would also work.  Like how gcc uses \"a.out\" as the default filename\n\n\n> What it does _not_ allow is to send the output to a downstream command for\n> postprocessing without introducing some magic token to say \"standard\n> output\" (e.g. \"git archive -f - | (cd ../foo && tar xf -)\").\n\nRight, so what's wrong with the magic token?  There's plenty of precedence.\n\n\n> If the default is to write to the standard output, we won't have all of\n> these issues.\n\nThese are issues?\n\n>  People who want a file can name the file by\n>\n>        git archive >my.file.tar\n\nI thought you didn't like this because then you dump binary to the\nconsole by default ?\n\n> and people who want to pipe (which is 99% of the use pattern for me) can\n> say\n>\n>        git archive | down stream commands.\n\nWhy would it be so bad to do:\n\ngit archive -f - | down stream commands\n\n?\n\nThis is the most logical way forward.  It keeps the command simple for\nsimple use cases (make an archive - \"git archive\")  but easily\nscalable for more complex use cases (add a  \"-f -\" if you want to do\nmagical things)\n\nJohn\n"},{"id":"122859","messageId":"7vtyza5nup.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"43d8ce650909101718j2f1f77cbgc347ee755145353f@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-11T00:25:34Z","receivedAt":"2009-09-11T00:25:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Tapsell <johnflux@gmail.com> writes:\n\n>>        git archive >my.file.tar\n>\n> I thought you didn't like this because then you dump binary to the\n> console by default ?\n\nNo. That objection came from Jakub and I said it did not make sense to me.\n\n> Why would it be so bad to do:\n>\n> git archive -f - | down stream commands\n\nAre you seriously asking \"why\" after I said this?\n\n>> and people who want to pipe (which is 99% of the use pattern for me) can\n>> say\n\nIf you really need it to be spelled out,...\n\nBecause I have to say \"-f -\" 99% of the time without no good reason.\n"},{"id":"122861","messageId":"7vpr9y5nap.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"9b18b3110909101619n6904a75dm10dd0b5717fb0d76@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-11T00:37:34Z","receivedAt":"2009-09-11T00:37:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"demerphq <demerphq@gmail.com> writes:\n\n> 2009/9/11 Junio C Hamano <gitster@pobox.com>:\n>> John Tapsell <johnflux@gmail.com> writes:\n>>\n>>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>>>> Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:\n>>>>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:\n>>>>\n>>>>> > First, it would be consistent with how ordinary archivers such as tar\n>>>>> > or zip are used, where you have to specify list of files to archive\n>>>>> > (in our case this list is HEAD).  Second, I'd rather not accidentally\n>>>>> > dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n>>>>> > output.\n>>>>>\n>>>>> That could be fixed by outputting to a file.  git format-patch outputs\n>>>>> to a file, so why wouldn't git achieve?\n>>>>\n>>>> \"git format-patch\" outputs to files because it generates _multiple_\n>>>> files; generating single patch is special case.  Also git-format-patch\n>>>> can generate file names from patch (commit) subject; it is not the case\n>>>> for \"git archive\" (what name should it use?).\n>>>\n>>> What if it used the current (or topleve) directory name?  Wouldn't\n>>> that work in most cases?\n>>\n>> Following along the same line of reasoning, it would work in most cases if\n>> the output is literally named \"archive.tar\".  If it is not the name the\n>> user wants, the user can \"mv\" afterwards, or give an explicit filename.\n>\n> Why not $sha1.tar?\n\nWhy not $(basename $(dirname $(pwd)))-$(date).tar instead?\n\nSee?  archive.tar is as good a compromise (so is a.out from cc).\n\n> Is it portable to assume that piping is always in binmode? From a\n> portability POV i could imagine piping being a problem in this\n> respect, and might be why tar provides a way to output to a file and\n> not just to a handle. For example ISTR that on windows piping is by\n> default in text mode. I think its not a showstopper there as you can\n> change it, but still, from a portability point of view you might not\n> want to depend on piping.\n\nWindows is not a showstopper to me ;-).\n\nBut seriously, I am glad that you brought up about a potential issue with\npipe.  There is one fairly important reason that it is better to say\n\n\tGZIP=-9 tar zcf here.tar.gz .\n\nthan to say\n\n\ttar cf - . | gzip -9 >here.tar.gz\n\nbut it has nothing to do with binmode.  The reason is error detection.\n\nFor exactly the same reason, if we can say\n\n\tgit archive -9 --output-file=here.tar.gz HEAD\n\nit is much better than having to say\n\n\tgit archive HEAD | gzip -9 >here.tar.gz\n\nIn other words, I am not opposed to supporting a \"--output-file here.tar\"\nat all.  I just do not want it to be mandatory.  I think that it is an\nugly kludge to force people to work it around with \"-f /dev/stdout\".\n\nOh wait.\n\nThat is exactly what we have, so what's the point of continuing this\ndiscussion any further?  Can we just _really_ stop this time, please?\n"},{"id":"122862","messageId":"20090911031519.GA6385@atjola.homenet","threadId":"20892","inReplyTo":"7vbpliaaxo.fsf@alter.siamese.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"Björn Steinbrink","fromEmail":"b.steinbrink@gmx.de","sentAt":"2009-09-11T03:15:19Z","receivedAt":"2009-09-11T03:15:19Z","isPatch":false,"sender":{"key":"b.steinbrink@gmx.de","avatar":"https://avatars.githubusercontent.com/u/230962?v=4"},"body":"On 2009.09.10 11:53:23 -0700, Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n> > First, it would be consistent with how ordinary archivers such as tar\n> > or zip are used, where you have to specify list of files to archive\n> > (in our case this list is HEAD).  Second, I'd rather not accidentally\n> > dump binary to terminal: \"git archive [HEAD]\" dumps archive to standard\n> > output.\n> \n> So does \"cat\".  I do not agree with your second point.\n\n\"cat $some_binary\" does, not just \"cat\". I guess Jakub's point was that\na command without arguments shouldn't just put some binary crap onto\nyour screen. Of course, \"git archive HEAD\" still does that, but I kind\nof he where he's coming from, being one of those that tends to run\n\"$some_command\" without arguments, just to see if it shows me some sort\nof short help.\n\nBjörn\n"},{"id":"122892","messageId":"alpine.LFD.2.01.0909110744030.3654@localhost.localdomain","threadId":"20892","inReplyTo":"4AA97B61.6030301@lsrfire.ath.cx","subject":"Re: obnoxious CLI complaints","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2009-09-11T14:47:01Z","receivedAt":"2009-09-11T14:47:01Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 11 Sep 2009, René Scharfe wrote:\n> \n> Using zlib directly avoids the overhead of a pipe and of buffering the\n> output for blocked writes; surprisingly (to me), it isn't any faster.\n\nIn fact, it should be slower.\n\nOn SMP, you're quite likely better off using the pipe, and compressing on \nanother CPU. Of course, it's usually the case that the compression is _so_ \nmuch slower than generating the tar-file (especially for the hot-cache \ncase) that it doesn't matter or the pipe overhead is even a slowdown.\n\nBut especially if generating the tar-file has some delays in it \n(cold-cache object lookup, whatever), the \"compress in separate process\" \nis likely simply better, because you can compress while the other process \nis looking up data for the tar.\n\n\t\t\t\tLinus\n"},{"id":"122919","messageId":"4AAAC8CE.8020302@lsrfire.ath.cx","threadId":"20892","inReplyTo":"alpine.LFD.2.01.0909110744030.3654@localhost.localdomain","subject":"Re: obnoxious CLI complaints","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-09-11T22:01:50Z","receivedAt":"2009-09-11T22:01:50Z","isPatch":false,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 11.09.2009 16:47, schrieb Linus Torvalds:\n>\n>\n> On Fri, 11 Sep 2009, René Scharfe wrote:\n>>\n>> Using zlib directly avoids the overhead of a pipe and of buffering the\n>> output for blocked writes; surprisingly (to me), it isn't any faster.\n>\n> In fact, it should be slower.\n>\n> On SMP, you're quite likely better off using the pipe, and compressing on\n> another CPU. Of course, it's usually the case that the compression is _so_\n> much slower than generating the tar-file (especially for the hot-cache\n> case) that it doesn't matter or the pipe overhead is even a slowdown.\n>\n> But especially if generating the tar-file has some delays in it\n> (cold-cache object lookup, whatever), the \"compress in separate process\"\n> is likely simply better, because you can compress while the other process\n> is looking up data for the tar.\n\nYes, that makes sense and can be seen here (quad core, Fedora 11, best\nof five consecutive runs, Linux kernel repo):\n\n\t# git v1.6.5-rc0\n\t$ time git archive --format=tar v2.6.31 | gzip -6 >/dev/null\n\n\treal\t0m16.591s\n\tuser\t0m19.769s\n\tsys\t0m0.474s\n\n\t# git v1.6.5-rc0 + patch\n\t$ time ../git/git archive --format=tar.gz -6 v2.6.31 >/dev/null\n\n\treal\t0m20.390s\n\tuser\t0m20.299s\n\tsys\t0m0.088s\n\nUser time is quite similar, real time is lower when using a pipe.\n\nBut what has bugged me since I added zip support is this result:\n\n\t# git v1.6.5-rc0\n\t$ time git archive --format=zip -6 v2.6.31 >/dev/null\n\n\treal\t0m16.471s\n\tuser\t0m16.340s\n\tsys\t0m0.128s\n\nI'd have expected this to be the slowest case, because it's compressing\nall files separately, i.e. it needs to create and flush the compression\ncontext lots of times instead of only once as in the two cases above.\nAnd it's sequential and uses zlib, just like the tar.gz format.  I\nsuspect the convenience function gzwrite() adds this overhead.\n\n\nOh, I just discovered pigz (http://zlib.net/pigz/), a parallel gzip:\n\n\t# git v1.6.5-rc0, pigz 2.1.5\n\t$ time git archive --format=tar v2.6.31 | pigz -6 >/dev/null\n\n\treal\t0m6.251s\n\tuser\t0m21.383s\n\tsys\t0m0.547s\n\nSo pipes win. :)  Still need to investigate why zip is as (relatively)\nfast as it is, though.\n\nRené\n"},{"id":"122922","messageId":"alpine.LFD.2.01.0909111510520.3654@localhost.localdomain","threadId":"20892","inReplyTo":"4AAAC8CE.8020302@lsrfire.ath.cx","subject":"Re: obnoxious CLI complaints","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2009-09-11T22:16:52Z","receivedAt":"2009-09-11T22:16:52Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 12 Sep 2009, René Scharfe wrote:\n> \n> But what has bugged me since I added zip support is this result:\n> \n> \t# git v1.6.5-rc0\n> \t$ time git archive --format=zip -6 v2.6.31 >/dev/null\n> \n> \treal\t0m16.471s\n> \tuser\t0m16.340s\n> \tsys\t0m0.128s\n> \n> I'd have expected this to be the slowest case, because it's compressing\n> all files separately, i.e. it needs to create and flush the compression\n> context lots of times instead of only once as in the two cases above.\n\nOh no, I think it's easily explained.\n\nCompressing many small files really is often cheaper than compressing one \nlarge one.\n\nWith lots of small files, you end up being very limited in the \nsearch-space, so the compression decisions get simpler. Compression in \ngeneral is not O(n), it's some non-linear factor, often something like \nO(n**2).\n\nOf course, all compression libraries have an upper bound on the \nnon-linearity (often expressed as a \"window size\"), so a particular \ncompression algorithm may end up being close to O(n) (with a huge \nconstant). But that upper bound will only kick in for large files, small \nfiles that fit entirely into the compression window will still see the \nunderlying O(n**2) or whatever.\n\nBut I have no actual numbers to back up the above blathering. But feel \nfree to try to compress 10 small files and compare it to compressing one \nfile that is as big as the sum. I bet you'll see it.\n\n\t\t\tLinus\n"},{"id":"122941","messageId":"20090912103156.GA30385@dpotapov.dyndns.org","threadId":"20892","inReplyTo":"ef38762f0909091709t7336d86dkd2f175e5b3a6a3f@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-09-12T10:31:56Z","receivedAt":"2009-09-12T10:31:56Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Wed, Sep 09, 2009 at 05:09:31PM -0700, Brendan Miller wrote:\n> On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n> > Brendan Miller <catphive@catphive.net> writes:\n> >>\n> >> This is what I want to do 90% of the time, so it should just have the\n> >> proper defaults, and not make me look at the man page every time I\n> >> want to use it.\n> >\n> > You learn those idioms.\n> \n> I guess. Is that a good thing?\n\nIn general, yes, because most of them exist for a good reason.\n\n> Is the goal of interface design to make\n> it difficult so I need to learn a lot of things, or easy so I can\n> remain blissfully ignorant but still do what I want?\n\nNeither. You cannot get what unless you have specified what you want,\nand for that you have to learn how to say that. Having good defaults is\nvery important, but the problem with choosing them is that people have\ndifferent preferences about them. For instance, you wanted the default\nprefix for git-archive to be $myproject. For me, a good default would be\neither $tag_name, or $myproject-$tag_name, or empty (as it is now!). So,\nwhat you propose is *never* a good default for me. Moreover, changing\nany default will cause a lot of pain for other people who use Git now.\nBesides, writing something like --prefix='' is very ugly. So, the\ncurrent default makes perfect sense.\n\n> >>\n> >> 7. Man pages: It's nice we have them, but we shouldn't need them to do\n> >> basic stuff. I rarely had to look at the man pages using svn, but\n> >> every single time I use git I have to dig into these things. Frankly,\n> >> I have better things to do than RTFM.\n> >\n> > Learn.  If you learn the philosophy behind git design, you would have\n> > much easier understanding and remembering git.\n> \n> I think what you mean by philosophy is the underlying data structures,\n> which are discussed in the manual \n\nI think I have read them a lot, but I do not remember any underlying\ndata structures described in them. What are you reading?\n\n> If I use GCC, do I need to know that it has a recursive descent\n> parser? That it is implemented with a garbage collector? No. I just\n> need to know that I give it C, and it gives me a binary.\n> \n> Example:\n> gcc main.c\n\nThe fallacy in your logic is that you compare two completely different\nthings thinking about them as almost identical. In case of GCC, the file\ncontains a program written in the C language. If you do not learn the C\nlanguage, you will not be able to use GCC. On the other hand, for Git\nany file is just bytes, but the command-line interface describes what\nyou want to do with them. There is no single action that would make\nsense in all cases, you have to specify what you want. Even with simple\ntools like sed or awk, you have to learn something before you can use\nthem.\n\n> >\n> > There is \"Git User's Manual\", \"The Git Community Book\", \"Pro Git\" and\n> > many other references.\n> \n> Yeah, I've been reading them. I'm saying that the docs are a crutch.\n> RTFM is the problem not the solution. It makes the user do more work\n> to avoid fixing usability issues.\n\nA usability issue exists when a person knows how to do that, but it is\ninconvenient or error-prone; or when a learning curve is too steep.\nBut when someone cannot use, let's say, a compiler, because he or she\nrefuses to read to learn the language, it is not a usability issue.\n\n\nDmitry\n"},{"id":"122973","messageId":"43d8ce650909121132n76cda485ycd53a0497e397960@mail.gmail.com","threadId":"20892","inReplyTo":"20090912103156.GA30385@dpotapov.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-09-12T18:32:09Z","receivedAt":"2009-09-12T18:32:09Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/9/12 Dmitry Potapov <dpotapov@gmail.com>:\n> On Wed, Sep 09, 2009 at 05:09:31PM -0700, Brendan Miller wrote:\n>> On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n>> > Brendan Miller <catphive@catphive.net> writes:\n>> >>\n>> >> This is what I want to do 90% of the time, so it should just have the\n>> >> proper defaults, and not make me look at the man page every time I\n>> >> want to use it.\n>> >\n>> > You learn those idioms.\n>>\n>> I guess. Is that a good thing?\n>\n> In general, yes, because most of them exist for a good reason.\n>\n>> Is the goal of interface design to make\n>> it difficult so I need to learn a lot of things, or easy so I can\n>> remain blissfully ignorant but still do what I want?\n>\n> Neither. You cannot get what unless you have specified what you want,\n> and for that you have to learn how to say that. Having good defaults is\n> very important, but the problem with choosing them is that people have\n> different preferences about them. For instance, you wanted the default\n> prefix for git-archive to be $myproject. For me, a good default would be\n> either $tag_name, or $myproject-$tag_name, or empty (as it is now!). So,\n> what you propose is *never* a good default for me. Moreover, changing\n> any default will cause a lot of pain for other people who use Git now.\n> Besides, writing something like --prefix='' is very ugly. So, the\n> current default makes perfect sense.\n\nAh, great logic.  You can't find a default that will suit everyone,\ntherefore don't bother.\n\n>> Yeah, I've been reading them. I'm saying that the docs are a crutch.\n>> RTFM is the problem not the solution. It makes the user do more work\n>> to avoid fixing usability issues.\n>\n> A usability issue exists when a person knows how to do that, but it is\n> inconvenient or error-prone; or when a learning curve is too steep.\n> But when someone cannot use, let's say, a compiler, because he or she\n> refuses to read to learn the language, it is not a usability issue.\n\nIt's a usability issue when it doesn't just do the right thing in the\nmajority of cases and lets you specify what you want it to do in the\nrest of the cases.\n\nJohn\n"},{"id":"122996","messageId":"20090912214428.GB30385@dpotapov.dyndns.org","threadId":"20892","inReplyTo":"43d8ce650909121132n76cda485ycd53a0497e397960@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-09-12T21:44:28Z","receivedAt":"2009-09-12T21:44:28Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Sat, Sep 12, 2009 at 09:32:09PM +0300, John Tapsell wrote:\n> 2009/9/12 Dmitry Potapov <dpotapov@gmail.com>:\n> > On Wed, Sep 09, 2009 at 05:09:31PM -0700, Brendan Miller wrote:\n> >> On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n> >> > Brendan Miller <catphive@catphive.net> writes:\n> >> >>\n> >> Is the goal of interface design to make\n> >> it difficult so I need to learn a lot of things, or easy so I can\n> >> remain blissfully ignorant but still do what I want?\n> >\n> > Neither. You cannot get what unless you have specified what you want,\n> > and for that you have to learn how to say that. Having good defaults is\n> > very important, but the problem with choosing them is that people have\n> > different preferences about them. For instance, you wanted the default\n> > prefix for git-archive to be $myproject. For me, a good default would be\n> > either $tag_name, or $myproject-$tag_name, or empty (as it is now!). So,\n> > what you propose is *never* a good default for me. Moreover, changing\n> > any default will cause a lot of pain for other people who use Git now.\n> > Besides, writing something like --prefix='' is very ugly. So, the\n> > current default makes perfect sense.\n> \n> Ah, great logic.  You can't find a default that will suit everyone,\n> therefore don't bother.\n\nI did not say \"don't bother\". On contrary, I said that defaults are very\nimportant, but, in this case, the current default makes far more sense\nthat what was proposed by Brendan.\n\n> \n> >> Yeah, I've been reading them. I'm saying that the docs are a crutch.\n> >> RTFM is the problem not the solution. It makes the user do more work\n> >> to avoid fixing usability issues.\n> >\n> > A usability issue exists when a person knows how to do that, but it is\n> > inconvenient or error-prone; or when a learning curve is too steep.\n> > But when someone cannot use, let's say, a compiler, because he or she\n> > refuses to read to learn the language, it is not a usability issue.\n> \n> It's a usability issue when it doesn't just do the right thing in the\n> majority of cases and lets you specify what you want it to do in the\n> rest of the cases.\n\nIt does the right thing for me, and not just in most cases, it does so\nin _all_ cases, because it does exactly it is told to do. And it is a\nvery important characteristics for any VCS, otherwise you can mess up\nthings easily. What is also good about Git is that it does not require\nmuch keystrokes to do even rather complex stuff. And many defaults and\ncommands are configurable, so you can adjust it to your workflow. So,\nI am not sure what your problem is.\n\n\nDmitry\n"},{"id":"122999","messageId":"43d8ce650909121521m3dbac12co7f5f2dcaf15190e7@mail.gmail.com","threadId":"20892","inReplyTo":"20090912214428.GB30385@dpotapov.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-09-12T22:21:43Z","receivedAt":"2009-09-12T22:21:43Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/9/13 Dmitry Potapov <dpotapov@gmail.com>:\n> On Sat, Sep 12, 2009 at 09:32:09PM +0300, John Tapsell wrote:\n>> 2009/9/12 Dmitry Potapov <dpotapov@gmail.com>:\n>> > On Wed, Sep 09, 2009 at 05:09:31PM -0700, Brendan Miller wrote:\n>> >> On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n>> >> > Brendan Miller <catphive@catphive.net> writes:\n>> >> >>\n>> >> Is the goal of interface design to make\n>> >> it difficult so I need to learn a lot of things, or easy so I can\n>> >> remain blissfully ignorant but still do what I want?\n>> >\n>> > Neither. You cannot get what unless you have specified what you want,\n>> > and for that you have to learn how to say that. Having good defaults is\n>> > very important, but the problem with choosing them is that people have\n>> > different preferences about them. For instance, you wanted the default\n>> > prefix for git-archive to be $myproject. For me, a good default would be\n>> > either $tag_name, or $myproject-$tag_name, or empty (as it is now!). So,\n>> > what you propose is *never* a good default for me. Moreover, changing\n>> > any default will cause a lot of pain for other people who use Git now.\n>> > Besides, writing something like --prefix='' is very ugly. So, the\n>> > current default makes perfect sense.\n>>\n>> Ah, great logic.  You can't find a default that will suit everyone,\n>> therefore don't bother.\n>\n> I did not say \"don't bother\". On contrary, I said that defaults are very\n> important, but, in this case, the current default makes far more sense\n> that what was proposed by Brendan.\n>\n>>\n>> >> Yeah, I've been reading them. I'm saying that the docs are a crutch.\n>> >> RTFM is the problem not the solution. It makes the user do more work\n>> >> to avoid fixing usability issues.\n>> >\n>> > A usability issue exists when a person knows how to do that, but it is\n>> > inconvenient or error-prone; or when a learning curve is too steep.\n>> > But when someone cannot use, let's say, a compiler, because he or she\n>> > refuses to read to learn the language, it is not a usability issue.\n>>\n>> It's a usability issue when it doesn't just do the right thing in the\n>> majority of cases and lets you specify what you want it to do in the\n>> rest of the cases.\n>\n> It does the right thing for me, and not just in most cases, it does so\n> in _all_ cases, because it does exactly it is told to do. And it is a\n> very important characteristics for any VCS, otherwise you can mess up\n> things easily. What is also good about Git is that it does not require\n> much keystrokes to do even rather complex stuff. And many defaults and\n> commands are configurable, so you can adjust it to your workflow. So,\n> I am not sure what your problem is.\n\nBecause I wouldn't call this just a few keystrokes to do the common case:\n\n    git archive --format=tar --prefix=HEAD/ HEAD | gzip > head.tar.gz\n\nI honestly don't understand the backlash against Brenden's point that\nthis could be made a bit simpler.\n\nJohn\n"},{"id":"123003","messageId":"4AAC224F.9080606@gmail.com","threadId":"20892","inReplyTo":"43d8ce650909121521m3dbac12co7f5f2dcaf15190e7@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"A Large Angry SCM","fromEmail":"gitzilla@gmail.com","sentAt":"2009-09-12T22:35:59Z","receivedAt":"2009-09-12T22:35:59Z","isPatch":false,"sender":{"key":"gitzilla@gmail.com","avatar":"https://gravatar.com/avatar/354625c442439908ff3dd99757dee330e29e9df7847472384faf7a00add247fb?d=mp&s=160"},"body":"John Tapsell wrote:\n> 2009/9/13 Dmitry Potapov <dpotapov@gmail.com>:\n>> On Sat, Sep 12, 2009 at 09:32:09PM +0300, John Tapsell wrote:\n>>> 2009/9/12 Dmitry Potapov <dpotapov@gmail.com>:\n>>>> On Wed, Sep 09, 2009 at 05:09:31PM -0700, Brendan Miller wrote:\n>>>>> On Wed, Sep 9, 2009 at 2:54 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n>>>>>> Brendan Miller <catphive@catphive.net> writes:\n>>>>> Is the goal of interface design to make\n>>>>> it difficult so I need to learn a lot of things, or easy so I can\n>>>>> remain blissfully ignorant but still do what I want?\n>>>> Neither. You cannot get what unless you have specified what you want,\n>>>> and for that you have to learn how to say that. Having good defaults is\n>>>> very important, but the problem with choosing them is that people have\n>>>> different preferences about them. For instance, you wanted the default\n>>>> prefix for git-archive to be $myproject. For me, a good default would be\n>>>> either $tag_name, or $myproject-$tag_name, or empty (as it is now!). So,\n>>>> what you propose is *never* a good default for me. Moreover, changing\n>>>> any default will cause a lot of pain for other people who use Git now.\n>>>> Besides, writing something like --prefix='' is very ugly. So, the\n>>>> current default makes perfect sense.\n>>> Ah, great logic.  You can't find a default that will suit everyone,\n>>> therefore don't bother.\n>> I did not say \"don't bother\". On contrary, I said that defaults are very\n>> important, but, in this case, the current default makes far more sense\n>> that what was proposed by Brendan.\n>>\n>>>>> Yeah, I've been reading them. I'm saying that the docs are a crutch.\n>>>>> RTFM is the problem not the solution. It makes the user do more work\n>>>>> to avoid fixing usability issues.\n>>>> A usability issue exists when a person knows how to do that, but it is\n>>>> inconvenient or error-prone; or when a learning curve is too steep.\n>>>> But when someone cannot use, let's say, a compiler, because he or she\n>>>> refuses to read to learn the language, it is not a usability issue.\n>>> It's a usability issue when it doesn't just do the right thing in the\n>>> majority of cases and lets you specify what you want it to do in the\n>>> rest of the cases.\n>> It does the right thing for me, and not just in most cases, it does so\n>> in _all_ cases, because it does exactly it is told to do. And it is a\n>> very important characteristics for any VCS, otherwise you can mess up\n>> things easily. What is also good about Git is that it does not require\n>> much keystrokes to do even rather complex stuff. And many defaults and\n>> commands are configurable, so you can adjust it to your workflow. So,\n>> I am not sure what your problem is.\n> \n> Because I wouldn't call this just a few keystrokes to do the common case:\n> \n>     git archive --format=tar --prefix=HEAD/ HEAD | gzip > head.tar.gz\n> \n> I honestly don't understand the backlash against Brenden's point that\n> this could be made a bit simpler.\n\nBe made simpler for whom? The first rule of defaults is that they are \nnever correct.\n\nAnd, to every one, if you don;t think like the way <SOME_PROGRAM> has \nit's defaults set and the developer(s) don't agree to change the default \nfor _everyone_ to what _you_ like, you can still use your shell's alias \nfacility to fix the situation for your own use case.\n\nTo channel Junio, why are we still having this discussion?\n"},{"id":"123005","messageId":"20090912224335.GC30385@dpotapov.dyndns.org","threadId":"20892","inReplyTo":"43d8ce650909121521m3dbac12co7f5f2dcaf15190e7@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-09-12T22:43:35Z","receivedAt":"2009-09-12T22:43:35Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Sun, Sep 13, 2009 at 01:21:43AM +0300, John Tapsell wrote:\n> \n> Because I wouldn't call this just a few keystrokes to do the common case:\n> \n>     git archive --format=tar --prefix=HEAD/ HEAD | gzip > head.tar.gz\n> \n> I honestly don't understand the backlash against Brenden's point that\n> this could be made a bit simpler.\n\nYou do not have to specify '--format=tar', because it is default. The\nprefix name is a matter of one's preferences. Brenden wanted it to be\n$myproject, while I have used three different versions. Now, you suggest\nsome other. IMHO, having it empty by default makes much more sense when\nthere is no obvious value on what most would agree. Finally, 'HEAD' is\nrequired, because we do not want 'git archive' being run without any\nparameter to write a binary file to the terminal. (Yes, it is foolish to\nrun command that you do not know to see what it does, but some people do\nthat, and we want all commands to be safe). BTW, I wonder whether use of\nHEAD is really common with git-archive. Normally, you would archive a\ntagged release, and then it is better to use the tag name to be sure\nthat you have archived the right thing.\n\n\nDmitry\n"},{"id":"123008","messageId":"43d8ce650909121608t2b9c4b9bw44104acceea26e12@mail.gmail.com","threadId":"20892","inReplyTo":"20090912224335.GC30385@dpotapov.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-09-12T23:08:50Z","receivedAt":"2009-09-12T23:08:50Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/9/13 Dmitry Potapov <dpotapov@gmail.com>:\n> On Sun, Sep 13, 2009 at 01:21:43AM +0300, John Tapsell wrote:\n>>\n>> Because I wouldn't call this just a few keystrokes to do the common case:\n>>\n>>     git archive --format=tar --prefix=HEAD/ HEAD | gzip > head.tar.gz\n>>\n>> I honestly don't understand the backlash against Brenden's point that\n>> this could be made a bit simpler.\n>\n> You do not have to specify '--format=tar', because it is default. The\n> prefix name is a matter of one's preferences. Brenden wanted it to be\n> $myproject, while I have used three different versions. Now, you suggest\n> some other. IMHO, having it empty by default makes much more sense when\n> there is no obvious value on what most would agree. Finally, 'HEAD' is\n> required, because we do not want 'git archive' being run without any\n> parameter to write a binary file to the terminal. (Yes, it is foolish to\n> run command that you do not know to see what it does, but some people do\n> that, and we want all commands to be safe). BTW, I wonder whether use of\n> HEAD is really common with git-archive. Normally, you would archive a\n> tagged release, and then it is better to use the tag name to be sure\n> that you have archived the right thing.\n\nAh, the manpage examples specifically give the --format=tar though.\n\nWhy not have  --format=tgz  then or something?  Or better yet, give\nthe filename on the command line and detect the format from the file\nextension.\n"},{"id":"123021","messageId":"7v3a6r5znq.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"43d8ce650909121608t2b9c4b9bw44104acceea26e12@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-13T02:47:21Z","receivedAt":"2009-09-13T02:47:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Tapsell <johnflux@gmail.com> writes:\n\n> Ah, the manpage examples specifically give the --format=tar though.\n\nSo what?\n\n> Why not have  --format=tgz  then or something?  Or better yet, give\n> the filename on the command line and detect the format from the file\n> extension.\n\nThat is an interesting enhancement and sounds like a useful feature.\n"},{"id":"123071","messageId":"1252863407-2598-1-git-send-email-dpotapov@gmail.com","threadId":"20892","inReplyTo":"7v3a6r5znq.fsf@alter.siamese.dyndns.org","subject":"[PATCH 1/2] git-archive: add '-o' as a alias for '--output'","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-09-13T17:36:46Z","receivedAt":"2009-09-13T17:36:46Z","isPatch":true,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"The '-o' option is commonly used in many tools to specify the output file.\nTyping '--output' every time is a bit too long to be a practical alternative\nto redirecting output. But specifying the output name has the advantage of\nmaking possible to guess the desired output format by filename extension.\n\nSigned-off-by: Dmitry Potapov <dpotapov@gmail.com>\n---\n\nPS I resend this patch because I forgot to include the git mailing list when\nI sent it before. Sorry for inconvinience...\n\n Documentation/git-archive.txt |    3 ++-\n archive.c                     |    2 +-\n builtin-archive.c             |    2 +-\n 3 files changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\nindex 92444dd..f7a3b95 100644\n--- a/Documentation/git-archive.txt\n+++ b/Documentation/git-archive.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n --------\n [verse]\n 'git archive' [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]\n-\t      [--output=<file>] [--worktree-attributes]\n+\t      [-o | --output=<file>] [--worktree-attributes]\n \t      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>\n \t      [path...]\n \n@@ -48,6 +48,7 @@ OPTIONS\n --prefix=<prefix>/::\n \tPrepend <prefix>/ to each filename in the archive.\n \n+-o::\n --output=<file>::\n \tWrite the archive to <file> instead of stdout.\n \ndiff --git a/archive.c b/archive.c\nindex 0bca9ca..73b8e8a 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -283,7 +283,7 @@ static int parse_archive_args(int argc, const char **argv,\n \t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n \t\tOPT_STRING(0, \"prefix\", &base, \"prefix\",\n \t\t\t\"prepend prefix to each pathname in the archive\"),\n-\t\tOPT_STRING(0, \"output\", &output, \"file\",\n+\t\tOPT_STRING('o', \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n \t\tOPT_BOOLEAN(0, \"worktree-attributes\", &worktree_attributes,\n \t\t\t\"read .gitattributes in working directory\"),\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex f9a4bea..565314b 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -71,7 +71,7 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \tconst char *output = NULL;\n \tconst char *remote = NULL;\n \tstruct option local_opts[] = {\n-\t\tOPT_STRING(0, \"output\", &output, \"file\",\n+\t\tOPT_STRING('o', \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n \t\tOPT_STRING(0, \"remote\", &remote, \"repo\",\n \t\t\t\"retrieve the archive from remote repository <repo>\"),\n-- \n1.6.4\n"},{"id":"123072","messageId":"1252863407-2598-2-git-send-email-dpotapov@gmail.com","threadId":"20892","inReplyTo":"1252863407-2598-1-git-send-email-dpotapov@gmail.com","subject":"[PATCH 2/2] teach git-archive to auto detect the output format","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-09-13T17:36:47Z","receivedAt":"2009-09-13T17:36:47Z","isPatch":true,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"When I type something like this:\n  git archive -o my-v2.0.zip v2.0\nit is almost certainly that I want to create a zip archive, and not\na tar file.\n\nThis patch teaches git-archive to auto detect the output format from the\nfile name. Currently, only '.zip' is supported. If the auto detect failed,\nthe tar format is used as default. The auto detect is not used when the\noutput format is specified explicitly.\n\nSigned-off-by: Dmitry Potapov <dpotapov@gmail.com>\n---\n\nOn Sat, Sep 12, 2009 at 07:47:21PM -0700, Junio C Hamano wrote:\n> John Tapsell <johnflux@gmail.com> writes:\n>_\n> > Why not have  --format=tgz  then or something?  Or better yet, give\n> > the filename on the command line and detect the format from the file\n> > extension.\n>_\n> That is an interesting enhancement and sounds like a useful feature.\n\nHere is my first attempt to implement that. I have not added 'tgz' yet,\nbut only auto detect the format from the output file name.\n\nPS I resend this patch because I forgot to include the git mailing list when\nI sent it before. Sorry for inconvinience...\n\n Documentation/git-archive.txt |   10 +++++++++-\n builtin-archive.c             |   25 +++++++++++++++++++++++++\n 2 files changed, 34 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\nindex f7a3b95..c6fb21c 100644\n--- a/Documentation/git-archive.txt\n+++ b/Documentation/git-archive.txt\n@@ -35,7 +35,9 @@ OPTIONS\n \n --format=<fmt>::\n \tFormat of the resulting archive: 'tar' or 'zip'.  The default\n-\tis 'tar'.\n+\tis 'tar', unless the output file is specified, and it has a known\n+\textension (such as '.zip') then the default for the output format\n+\twill be determined by this extension.\n \n -l::\n --list::\n@@ -130,6 +132,12 @@ git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs\n \tPut everything in the current head's Documentation/ directory\n \tinto 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.\n \n+git archive -o latest.zip HEAD::\n+\n+\tCreate a Zip archive that contains the contents of the latest\n+\tcommit on the current branch. Note that the output format is\n+\tspecified implicitly by the extension of the output file.\n+\n \n SEE ALSO\n --------\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex 565314b..878c6b2 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -60,6 +60,17 @@ static int run_remote_archiver(int argc, const char **argv,\n \treturn !!rv;\n }\n \n+static const char* format_from_name(const char *filename)\n+{\n+\tconst char *ext = strrchr(filename, '.');\n+\tif (!ext)\n+\t\treturn NULL;\n+\text++;\n+\tif (!strcasecmp(ext, \"zip\"))\n+\t\treturn \"zip\";\n+\treturn NULL;\n+}\n+\n #define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \t\\\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | \t\\\n \t\t\t     PARSE_OPT_KEEP_UNKNOWN |\t\\\n@@ -70,6 +81,7 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \tconst char *exec = \"git-upload-archive\";\n \tconst char *output = NULL;\n \tconst char *remote = NULL;\n+\tconst char *format = NULL;\n \tstruct option local_opts[] = {\n \t\tOPT_STRING('o', \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n@@ -77,14 +89,27 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \t\t\t\"retrieve the archive from remote repository <repo>\"),\n \t\tOPT_STRING(0, \"exec\", &exec, \"cmd\",\n \t\t\t\"path to the remote git-upload-archive command\"),\n+\t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n \t\tOPT_END()\n \t};\n+\tchar fmt_opt[32];\n \n \targc = parse_options(argc, argv, prefix, local_opts, NULL,\n \t\t\t     PARSE_OPT_KEEP_ALL);\n \n \tif (output)\n+\t{\n \t\tcreate_output_file(output);\n+\t\tif (!format)\n+\t\t\tformat = format_from_name(output);\n+\t}\n+\n+\tif (format)\n+\t{\n+\t\tsprintf(fmt_opt, \"--format=%s\", format);\n+\t\targv[argc++] = fmt_opt;\n+\t\targv[argc] = NULL;\n+\t}\n \n \tif (remote)\n \t\treturn run_remote_archiver(argc, argv, remote, exec);\n-- \n1.6.4\n"},{"id":"123076","messageId":"7v4or6sngc.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"1252863407-2598-1-git-send-email-dpotapov@gmail.com","subject":"Re: [PATCH 1/2] git-archive: add '-o' as a alias for '--output'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-13T18:34:43Z","receivedAt":"2009-09-13T18:34:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dmitry Potapov <dpotapov@gmail.com> writes:\n\n> The '-o' option is commonly used in many tools to specify the output file.\n> Typing '--output' every time is a bit too long to be a practical alternative\n> to redirecting output. But specifying the output name has the advantage of\n> making possible to guess the desired output format by filename extension.\n>\n> Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>\n> ---\n> ...\n> diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\n> index 92444dd..f7a3b95 100644\n> --- a/Documentation/git-archive.txt\n> +++ b/Documentation/git-archive.txt\n> @@ -48,6 +48,7 @@ OPTIONS\n>  --prefix=<prefix>/::\n>  \tPrepend <prefix>/ to each filename in the archive.\n>  \n> +-o::\n>  --output=<file>::\n>  \tWrite the archive to <file> instead of stdout.\n\nI think this patch is very reasonable, except for this hunk, which would\nwant to say \"-o <file>::\" instead.  I'll see if there are comments from\nothers and if there is none, apply this patch with that minor tweak.\n\nThanks.\n"},{"id":"123097","messageId":"7vzl8yr81j.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"1252863407-2598-2-git-send-email-dpotapov@gmail.com","subject":"Re: [PATCH 2/2] teach git-archive to auto detect the output format","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-13T18:52:56Z","receivedAt":"2009-09-13T18:52:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dmitry Potapov <dpotapov@gmail.com> writes:\n\n> diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\n> index f7a3b95..c6fb21c 100644\n> --- a/Documentation/git-archive.txt\n> +++ b/Documentation/git-archive.txt\n> @@ -35,7 +35,9 @@ OPTIONS\n>  \n>  --format=<fmt>::\n>  \tFormat of the resulting archive: 'tar' or 'zip'.  The default\n> -\tis 'tar'.\n> +\tis 'tar', unless the output file is specified, and it has a known\n> +\textension (such as '.zip') then the default for the output format\n> +\twill be determined by this extension.\n\nOnce it is _determined_, then it is not the default anymore.\n\n\tIf this option is not given, and the output file is specified, the\n\tformat is inferred from the filename if possible (e.g. writing to\n\t\"foo.zip\" makes the output to be in the zip format).  Otherwise\n\tthe output format is `tar`.\n\n> @@ -130,6 +132,12 @@ git archive --format=zip\n>  \tPut everything in the current head's Documentation/ directory\n>  \tinto 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.\n>  \n> +git archive -o latest.zip HEAD::\n> +\n> +\tCreate a Zip archive that contains the contents of the latest\n> +\tcommit on the current branch. Note that the output format is\n> +\tspecified implicitly by the extension of the output file.\n> +\n\nPerhaps \"s/specified implicitly/inferred/\" but that is a minor point.\n\n> diff --git a/builtin-archive.c b/builtin-archive.c\n> index 565314b..878c6b2 100644\n> --- a/builtin-archive.c\n> +++ b/builtin-archive.c\n> @@ -77,14 +89,27 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n>  \t\t\t\"retrieve the archive from remote repository <repo>\"),\n>  \t\tOPT_STRING(0, \"exec\", &exec, \"cmd\",\n>  \t\t\t\"path to the remote git-upload-archive command\"),\n> +\t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n>  \t\tOPT_END()\n>  \t};\n> +\tchar fmt_opt[32];\n>  \n>  \targc = parse_options(argc, argv, prefix, local_opts, NULL,\n>  \t\t\t     PARSE_OPT_KEEP_ALL);\n>  \n>  \tif (output)\n> +\t{\n\nOn the same line, i.e. \"if (output) {\".\n\n>  \t\tcreate_output_file(output);\n> +\t\tif (!format)\n> +\t\t\tformat = format_from_name(output);\n> +\t}\n> +\n> +\tif (format)\n> +\t{\n\nOn the same line, i.e. \"if (format) {\".\n\n> +\t\tsprintf(fmt_opt, \"--format=%s\", format);\n> +\t\targv[argc++] = fmt_opt;\n> +\t\targv[argc] = NULL;\n\nDid you make sure you are allowed to write into argv[] and the array is\nlarge enough?  You probably need to make a copy of the array.\n\nOtherwise, the idea feels sound.\n"},{"id":"123101","messageId":"20090913201336.GG30385@dpotapov.dyndns.org","threadId":"20892","inReplyTo":"7v4or6sngc.fsf@alter.siamese.dyndns.org","subject":"[PATCH v2 1/2] git-archive: add '-o' as a alias for '--output'","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-09-13T20:13:36Z","receivedAt":"2009-09-13T20:13:36Z","isPatch":true,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"The '-o' option is commonly used in many tools to specify the output file.\nTyping '--output' every time is a bit too long to be a practical alternative\nto redirecting output. But specifying the output name has the advantage of\nmaking possible to guess the desired output format by filename extension.\n\nSigned-off-by: Dmitry Potapov <dpotapov@gmail.com>\n---\n\nOn Sun, Sep 13, 2009 at 11:34:43AM -0700, Junio C Hamano wrote:\n> I think this patch is very reasonable, except for this hunk, which would\n> want to say \"-o <file>::\" instead.\n\nCorrected.\n\n Documentation/git-archive.txt |    3 ++-\n archive.c                     |    2 +-\n builtin-archive.c             |    2 +-\n 3 files changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\nindex 92444dd..1917f2e 100644\n--- a/Documentation/git-archive.txt\n+++ b/Documentation/git-archive.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n --------\n [verse]\n 'git archive' [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]\n-\t      [--output=<file>] [--worktree-attributes]\n+\t      [-o | --output=<file>] [--worktree-attributes]\n \t      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>\n \t      [path...]\n \n@@ -48,6 +48,7 @@ OPTIONS\n --prefix=<prefix>/::\n \tPrepend <prefix>/ to each filename in the archive.\n \n+-o <file>::\n --output=<file>::\n \tWrite the archive to <file> instead of stdout.\n \ndiff --git a/archive.c b/archive.c\nindex 0bca9ca..73b8e8a 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -283,7 +283,7 @@ static int parse_archive_args(int argc, const char **argv,\n \t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n \t\tOPT_STRING(0, \"prefix\", &base, \"prefix\",\n \t\t\t\"prepend prefix to each pathname in the archive\"),\n-\t\tOPT_STRING(0, \"output\", &output, \"file\",\n+\t\tOPT_STRING('o', \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n \t\tOPT_BOOLEAN(0, \"worktree-attributes\", &worktree_attributes,\n \t\t\t\"read .gitattributes in working directory\"),\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex f9a4bea..565314b 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -71,7 +71,7 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \tconst char *output = NULL;\n \tconst char *remote = NULL;\n \tstruct option local_opts[] = {\n-\t\tOPT_STRING(0, \"output\", &output, \"file\",\n+\t\tOPT_STRING('o', \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n \t\tOPT_STRING(0, \"remote\", &remote, \"repo\",\n \t\t\t\"retrieve the archive from remote repository <repo>\"),\n-- \n1.6.5.rc1.2.g6bb993\n"},{"id":"123102","messageId":"20090913201701.GH30385@dpotapov.dyndns.org","threadId":"20892","inReplyTo":"7vzl8yr81j.fsf@alter.siamese.dyndns.org","subject":"[PATCH v2 2/2] teach git-archive to auto detect the output format","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2009-09-13T20:17:01Z","receivedAt":"2009-09-13T20:17:01Z","isPatch":true,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"When I type something like this:\n  git archive -o my-v2.0.zip v2.0\nit is almost certainly that I want to create a zip archive, and not\na tar file.\n\nThis patch teaches git-archive to auto detect the output format from the\nfile name. Currently, only '.zip' is supported. If the auto detect failed,\nthe tar format is used as before. The auto detect is not used when the\noutput format is specified explicitly.\n\nSigned-off-by: Dmitry Potapov <dpotapov@gmail.com>\n---\n\nI have corrected all remarks except this:\n\nOn Sun, Sep 13, 2009 at 11:52:56AM -0700, Junio C Hamano wrote:\n> > +\t\tsprintf(fmt_opt, \"--format=%s\", format);\n> > +\t\targv[argc++] = fmt_opt;\n> > +\t\targv[argc] = NULL;\n> \n> Did you make sure you are allowed to write into argv[] and the array is\n> large enough?  You probably need to make a copy of the array.\n\nEither --output or --format option was used before, and this option is\nextracted from argv[] by parse_options(). So it should be space for at\nleast one argument in argv.\n\n\n Documentation/git-archive.txt |   13 +++++++++++--\n builtin-archive.c             |   25 ++++++++++++++++++++++++-\n 2 files changed, 35 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\nindex 1917f2e..3d1c1e7 100644\n--- a/Documentation/git-archive.txt\n+++ b/Documentation/git-archive.txt\n@@ -34,8 +34,11 @@ OPTIONS\n -------\n \n --format=<fmt>::\n-\tFormat of the resulting archive: 'tar' or 'zip'.  The default\n-\tis 'tar'.\n+\tFormat of the resulting archive: 'tar' or 'zip'. If this option\n+\tis not given, and the output file is specified, the format is\n+\tinferred from the filename if possible (e.g. writing to \"foo.zip\"\n+\tmakes the output to be in the zip format). Otherwise the output\n+\tformat is `tar`.\n \n -l::\n --list::\n@@ -130,6 +133,12 @@ git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs\n \tPut everything in the current head's Documentation/ directory\n \tinto 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.\n \n+git archive -o latest.zip HEAD::\n+\n+\tCreate a Zip archive that contains the contents of the latest\n+\tcommit on the current branch. Note that the output format is\n+\tinferred by the extension of the output file.\n+\n \n SEE ALSO\n --------\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex 565314b..6efba6f 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -60,6 +60,17 @@ static int run_remote_archiver(int argc, const char **argv,\n \treturn !!rv;\n }\n \n+static const char* format_from_name(const char *filename)\n+{\n+\tconst char *ext = strrchr(filename, '.');\n+\tif (!ext)\n+\t\treturn NULL;\n+\text++;\n+\tif (!strcasecmp(ext, \"zip\"))\n+\t\treturn \"zip\";\n+\treturn NULL;\n+}\n+\n #define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \t\\\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | \t\\\n \t\t\t     PARSE_OPT_KEEP_UNKNOWN |\t\\\n@@ -70,6 +81,7 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \tconst char *exec = \"git-upload-archive\";\n \tconst char *output = NULL;\n \tconst char *remote = NULL;\n+\tconst char *format = NULL;\n \tstruct option local_opts[] = {\n \t\tOPT_STRING('o', \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n@@ -77,14 +89,25 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \t\t\t\"retrieve the archive from remote repository <repo>\"),\n \t\tOPT_STRING(0, \"exec\", &exec, \"cmd\",\n \t\t\t\"path to the remote git-upload-archive command\"),\n+\t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n \t\tOPT_END()\n \t};\n+\tchar fmt_opt[32];\n \n \targc = parse_options(argc, argv, prefix, local_opts, NULL,\n \t\t\t     PARSE_OPT_KEEP_ALL);\n \n-\tif (output)\n+\tif (output) {\n \t\tcreate_output_file(output);\n+\t\tif (!format)\n+\t\t\tformat = format_from_name(output);\n+\t}\n+\n+\tif (format) {\n+\t\tsprintf(fmt_opt, \"--format=%s\", format);\n+\t\targv[argc++] = fmt_opt;\n+\t\targv[argc] = NULL;\n+\t}\n \n \tif (remote)\n \t\treturn run_remote_archiver(argc, argv, remote, exec);\n-- \n1.6.5.rc1.2.g6bb993\n"},{"id":"123113","messageId":"7v4or6o7qf.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"20090913201701.GH30385@dpotapov.dyndns.org","subject":"Re: [PATCH v2 2/2] teach git-archive to auto detect the output format","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-13T21:27:52Z","receivedAt":"2009-09-13T21:27:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dmitry Potapov <dpotapov@gmail.com> writes:\n\n> On Sun, Sep 13, 2009 at 11:52:56AM -0700, Junio C Hamano wrote:\n>> > +\t\tsprintf(fmt_opt, \"--format=%s\", format);\n>> > +\t\targv[argc++] = fmt_opt;\n>> > +\t\targv[argc] = NULL;\n>> \n> Either --output or --format option was used before, and this option is\n> extracted from argv[] by parse_options(). So it should be space for at\n> least one argument in argv.\n\nTo my taste, that is a unwarranted (on the borderline) assumption of what\nparse_options() does, but I'll let it pass with some additional comment to\nwarn readers of the code.\n\nApplied.\n"},{"id":"123395","messageId":"ef38762f0909161748u32ad56bcya3314fe28fd06ffe@mail.gmail.com","threadId":"20892","inReplyTo":"7v3a6r5znq.fsf@alter.siamese.dyndns.org","subject":"Re: obnoxious CLI complaints","fromName":"Brendan Miller","fromEmail":"catphive@catphive.net","sentAt":"2009-09-17T00:48:32Z","receivedAt":"2009-09-17T00:48:32Z","isPatch":false,"sender":{"key":"catphive@catphive.net","avatar":"https://gravatar.com/avatar/d6048400272e913886f5ee25c1bca2020dc014547231c1dc148fdfa1631e31d3?d=mp&s=160"},"body":"On Sun, Sep 13, 2009 at 11:47 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> John Tapsell <johnflux@gmail.com> writes:\n>\n>> Ah, the manpage examples specifically give the --format=tar though.\n>\n> So what?\n\nThat looks like a manpage bug. In the version I have 1.6.4 the format\nfor archive is given like this:\n\n git archive --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]\n                         [--output=<file>] [--worktree-attributes]\n                         [--remote=<repo> [--exec=<git-upload-archive>]] <tree-i\nsh>\n                         [path...]\n\nSo --format isn't marked as optional. Later in the manpage it mentions\ntar as the default, but that contradicts this, and the examples use\n--format=tar, so it's easy to miss.\n\n>\n>> Why not have  --format=tgz  then or something?  Or better yet, give\n>> the filename on the command line and detect the format from the file\n>> extension.\n>\n> That is an interesting enhancement and sounds like a useful feature.\n>\nI do like that idea.\n\ngit archive --output=myarchive.tar.gz HEAD is a bit more\nstraightforward, and still lets people pipe in the old way if they\nwant to.\n\nI think someone mentioned we're already linking the requisite library?\nOtherwise, you can always open up a pipe programmatically within git.\nDon't you guys do something like that for ssh? I seem to recall it\ncomplaining that ssh couldn't be found on windows, but maybe it was\njust the library.\n\nPrefix could be myarchive. I guess some people have more specific\nrequirements, but I usually just want it to be *sometime* so it\ndoesn't spew out tons of files into the directory I decompress it\ninto.\n\nBrendan\n"},{"id":"123396","messageId":"7vk4zyuzrd.fsf@alter.siamese.dyndns.org","threadId":"20892","inReplyTo":"ef38762f0909161748u32ad56bcya3314fe28fd06ffe@mail.gmail.com","subject":"Re: obnoxious CLI complaints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-17T01:27:18Z","receivedAt":"2009-09-17T01:27:18Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brendan Miller <catphive@catphive.net> writes:\n\n> On Sun, Sep 13, 2009 at 11:47 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> John Tapsell <johnflux@gmail.com> writes:\n>>\n>>> Ah, the manpage examples specifically give the --format=tar though.\n>>\n>> So what?\n>\n> That looks like a manpage bug. In the version I have 1.6.4 the format\n> for archive is given like this:\n>\n>  git archive --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]\n>                          [--output=<file>] [--worktree-attributes]\n>                          [--remote=<repo> [--exec=<git-upload-archive>]] <tree-i\n> sh>\n>                          [path...]\n>\n> So --format isn't marked as optional.\n\nAhh, that would indeed be a documentation bug.\n\n82d97da (Documentation: git-archive: mark --format as optional in summary,\n2009-08-27) fixed it already, so upcoming 1.6.5 should have that fix.\n\nThanks.\n"}]}