{"thread":{"id":"28281","subject":"git 'new' alias","startedAt":"2011-09-01T19:30:16Z","lastAt":"2011-09-05T20:41:18Z","messageCount":5,"participants":["Thiago Farina","Matthieu Moy","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"174702","messageId":"CACnwZYfo2E0SFfFrYzUktAZYwqgyX_J4KgFQD5kqXToGmip3Lg@mail.gmail.com","threadId":"28281","inReplyTo":null,"subject":"git 'new' alias","fromName":"Thiago Farina","fromEmail":"tfransosi@gmail.com","sentAt":"2011-09-01T19:30:16Z","receivedAt":"2011-09-01T19:30:16Z","isPatch":false,"sender":{"key":"tfransosi@gmail.com","avatar":"https://avatars.githubusercontent.com/u/970071?v=4"},"body":"Hi,\n\nCould we change the 'new' alias in the wiki page,\n\nfrom:\nnew = !sh -c 'git log $1@{1}..$1@{0} \"$@\"'\n\nto:\nnew = !git log $1@{1}..$1@{0} \"$@\"\n\n?\n\nThe former doesn't get auto-completion, while the second yes.\n\nhttps://git.wiki.kernel.org/index.php/Aliases#What.27s_new.3F\n"},{"id":"174704","messageId":"vpqei00m4pf.fsf@bauges.imag.fr","threadId":"28281","inReplyTo":"CACnwZYfo2E0SFfFrYzUktAZYwqgyX_J4KgFQD5kqXToGmip3Lg@mail.gmail.com","subject":"Re: git 'new' alias","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-09-01T19:40:28Z","receivedAt":"2011-09-01T19:40:28Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Thiago Farina <tfransosi@gmail.com> writes:\n\n> Hi,\n>\n> Could we change the 'new' alias in the wiki page,\n>\n> from:\n> new = !sh -c 'git log $1@{1}..$1@{0} \"$@\"'\n>\n> to:\n> new = !git log $1@{1}..$1@{0} \"$@\"\n>\n> ?\n\nGo on. I think I'm the one who added it, and I didn't know $1 and $@\nwould work without \"sh -c\", but I guess my version results in calling\nstg like sh -c \"sh -c 'git log ...'\" which is a bit overkill ;-).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"174708","messageId":"20110901211747.GA16308@sigill.intra.peff.net","threadId":"28281","inReplyTo":"vpqei00m4pf.fsf@bauges.imag.fr","subject":"Re: git 'new' alias","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-09-01T21:17:47Z","receivedAt":"2011-09-01T21:17:47Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Sep 01, 2011 at 09:40:28PM +0200, Matthieu Moy wrote:\n\n> Thiago Farina <tfransosi@gmail.com> writes:\n> \n> > Hi,\n> >\n> > Could we change the 'new' alias in the wiki page,\n> >\n> > from:\n> > new = !sh -c 'git log $1@{1}..$1@{0} \"$@\"'\n> >\n> > to:\n> > new = !git log $1@{1}..$1@{0} \"$@\"\n> >\n> > ?\n> \n> Go on. I think I'm the one who added it, and I didn't know $1 and $@\n> would work without \"sh -c\", but I guess my version results in calling\n> stg like sh -c \"sh -c 'git log ...'\" which is a bit overkill ;-).\n\nHmm. Aren't both of these somewhat wrong?\n\nGit will assume your alias is a shell snippet, append the\nspace-separated shell-quoted arguments provided to the alias to your\nsnippet, and then hand the result to the shell.\n\nWe can simulate the first one with:\n\n  $ git config alias.one\n  !sh -c 'echo $1@{1}..$1@{0} \"$@\"'\n\nwhich gives:\n\n  $ git one foo\n  @{1}..@{0}\n\nOops, that's not right. You need a placeholder for $0. So make it:\n\n  $ git config alias.one\n  !sh -c 'echo $1@{1}..$1@{0} \"$@\"' --\n\nand now you get:\n\n  $ git one foo\n  foo@{1}..foo@{0} foo\n\nWait, what's that extra \"foo\" on the end? I'm not sure of the intent.\nEither it is totally superfluous, or perhaps it was meant to pass along\nother options, like path limiters. In the former case, you just want:\n\n  !sh -c 'echo $1@{1}..$1@{0}' --\n\nand in the latter case, you actually want to shift off $1 and provide\nthe rest of the options. Of course, for this particular alias, it so\nhappens that adding an extra $1 is equivalent to $1@{0}, which is\nsuperfluous but harmless. More on that in a minute.\n\nHow about the second one:\n\n  $ git config alias.two\n  !echo $1@{1}..$1@{0} \"$@\"\n\nwhich yields:\n\n  $ git two foo\n  foo@{1}..foo@{0} foo foo\n\nNow we have two extra foos! One is from a superfluous use of \"$@\", which\nis no longer necessary to pass along extra args, since we aren't\ninvoking a subshell. So we are better off with:\n\n  $ git config alias.two\n  !echo $1@{1}..$1@{0}\n\nwhich yields:\n\n  $ git two foo\n  foo@{1}..foo@{0} foo\n\nBetter, but we still get our superfluous \"foo\" at the end. And there's\nno way to get rid of it here, since it is appended to our shell snippet.\nWe can't just shift it away.\n\nSo in this particular alias, you can live without the subshell wrapper,\nand the final alias.two I mentioned is OK. If you're satisfied with\nthat, you can stop reading now. I still find the repeated refname a\nlittle hack-ish, though, as it doesn't extend to other aliases\nnaturally.\n\nYou mentioned the ugliness in having the shell call itself. Weep for the\nquoting nightmare that is:\n\n  $ git config alias.one\n  !sh -c 'echo $1@{1}..$1@{0} \"$@\"' --\n\n  $ GIT_TRACE=1 git one foo\n  trace: exec: 'sh' '-c' 'sh -c '\\''echo $1@{1}..$1@{0} \"$@\"'\\'' -- \"$@\"' 'sh -c '\\''echo $1@{1}..$1@{0} \"$@\"'\\'' --' 'foo'\n\nFortunately, we can do a little better using shell functions. I would\nwrite this as:\n\n  $ git config alias.one\n  !f() { r=$1; shift; echo $r@{1}..$r@{0} \"$@\"; }; f\n\n  $ git one foo\n  foo@{1}..foo@{0}\n\n  $ git one foo bar\n  foo@{1}..foo@{0} bar\n\nwhich I think was the original intent (modulo me replacing \"git log\"\nwith \"echo\" for debugging, of course). And if you peek at GIT_TRACE\noutput, we only invoke a single shell.\n\nNow back to the original complaint: no shell completion. For that, I\nwould simply add:\n\n  _git_new() {\n    __git_complete_revlist\n  }\n\nto my .bashrc. Yeah, it's a little more work than having the completion\nautomatically figure out that \"new\" takes the same arguments as \"git\nlog\", but it works in the general case.\n\n-Peff\n"},{"id":"174875","messageId":"vpqipp77xpb.fsf@bauges.imag.fr","threadId":"28281","inReplyTo":"20110901211747.GA16308@sigill.intra.peff.net","subject":"Re: git 'new' alias","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-09-05T16:36:48Z","receivedAt":"2011-09-05T16:36:48Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jeff King <peff@peff.net> writes:\n\n>   $ git config alias.one\n>   !f() { r=$1; shift; echo $r@{1}..$r@{0} \"$@\"; }; f\n\n(which, I've just discovered, should be written as\n\n[alias]\n        one = \"!f() { r=$1; shift; echo $r@{1}..$r@{0} \"$@\"; }; f\"\n\notherwise \"git config\" messes up with the ; in the line)\n\n> which I think was the original intent (modulo me replacing \"git log\"\n> with \"echo\" for debugging, of course).\n\nThe original intent was mis-specified ;-).\n\nI think I originally made the alias to do\n\ngit new               # give me new stuff on current branch\ngit new origin/master # same, for origin/master\n\nand tried to enrich it to allow\n\ngit new master --oneline\n\nwithout thinking about what\n\ngit new --oneline\n\nshould do (and obviously, without really testing it, I guess I had one\nversion of the alias allowing each senario, and none allowing all of\nthem).\n\nI now have this, which is really ugly in a config file, but does the\nDWIMery I want:\n\n\tnew = \"!f () { if echo \\\"$1\\\" | grep -q -e '^-' -e '^$'; then r=; else r=$1; shift; fi; git log $r@{1}..$r@{0} \\\"$@\\\"; } && f\"\n\n(this one has even been vaguely tested ;-) )\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"174886","messageId":"20110905204118.GA4221@sigill.intra.peff.net","threadId":"28281","inReplyTo":"vpqipp77xpb.fsf@bauges.imag.fr","subject":"Re: git 'new' alias","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-09-05T20:41:18Z","receivedAt":"2011-09-05T20:41:18Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 05, 2011 at 06:36:48PM +0200, Matthieu Moy wrote:\n\n> >   $ git config alias.one\n> >   !f() { r=$1; shift; echo $r@{1}..$r@{0} \"$@\"; }; f\n> \n> (which, I've just discovered, should be written as\n> \n> [alias]\n>         one = \"!f() { r=$1; shift; echo $r@{1}..$r@{0} \"$@\"; }; f\"\n> \n> otherwise \"git config\" messes up with the ; in the line)\n\nYes, it definitely needs quotes. However, you also need to\nbackslash-escape the quotes inside, or you get:\n\n  $ git config alias.one\n  !f() { r=$1; shift; echo $r@{1}..$r@{0} $@; }; f\n\nwhich will accidentally split any arguments with whitespace.\n\n> I now have this, which is really ugly in a config file, but does the\n> DWIMery I want:\n> \n> \tnew = \"!f () { if echo \\\"$1\\\" | grep -q -e '^-' -e '^$'; then r=; else r=$1; shift; fi; git log $r@{1}..$r@{0} \\\"$@\\\"; } && f\"\n\nInstead of piping into grep, I would do:\n\n  case \"$1\" in\n    \"\"|-*) ;;\n    *) r=$1; shift ;;\n  esac\n\nwhich saves a process (and is IMHO a little more obvious).\n\nAs far as getting ugly for a config file, I would note that:\n\n  1. You can always drop a git-new script in your PATH. :)\n\n  2. You can backslash-escape literal newlines in config entries. It's\n     not amazingly pretty, but it can help:\n\n      [alias]\n        new = \"! \\\n          f() { \\\n            case \\\"$1\\\" in \\\n              ''|-*) ;; \\\n              *) r=$1; shift ;; \\\n            esac; \\\n            git log $r@{1}..$r@{0} \\\"$@\\\"; \\\n          }; \\\n          f\"\n\n-Peff\n\nPS I use a similar alias, and I have found that defaulting to \"--oneline\n--graph --boundary $r@{0}...@r{1}\" is quite nice for seeing how you\ndiffer from upstream.\n"}]}