Re: Weird behavior of shell variables in git aliases

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Mar 21, 2011 at 03:33:25PM -0700, Junio C Hamano wrote:

> >> But interestingly, that's _not_ the behavior as of Erik's 7f51f8b
> >> (alias: use run_command api to execute aliases, 2011-01-07), which is in
> >> master but not yet released. With that, we end up executing:
> >>
> >>   sh -c 'echo $1 && echo $1 "$@"' 'echo $1 && echo $1' 'foo'
> [...]
> >
> > Oh, I should have been paying a bit more attention.  I've been assuming
> > that we were turning "!anything" into { "sh", "-c", "anything", "-" }
> > followed by the user supplied arguments.

Yeah, I think that would be more useful in general, but...

> The attached quick hack gives
> 
>   $ git config alias.silly
>   !echo hello $1; echo $# args, bye!
>   $ GIT_TRACE=1 ./git silly world funny
>   trace: exec: 'git-silly' 'world' 'funny'
>   trace: run_command: 'git-silly' 'world' 'funny'
>   trace: run_command: 'sh' '-c' 'echo hello $1; echo $# args, bye'\!'' '-' 'world' 'funny'
>   trace: exec: 'sh' '-c' 'echo hello $1; echo $# args, bye'\!''
>   '-' 'world' 'funny'
>   hello world
>   2 args, bye!
> 
> but it would penalize a properly written alias that uses "sh -c <it> -"
> trick itself by double forking, which is not very nice and I am unhappy
> about.

Doesn't it also break a lot of other more garden-variety aliases that
rely on the automagic "$@", like:

  $ git config alias.log-nopager
  !git --no-pager log

  $ GIT_TRACE=1 git.v1.7.4 log-nopager --oneline
  trace: exec: 'git-log-nopager' '--oneline'
  trace: run_command: 'git-log-nopager' '--oneline'
  trace: alias to shell cmd: log-nopager => git --no-pager log '--oneline'
  trace: built-in: git 'log' '--oneline'
  93c7d44 foo

  $ GIT_TRACE=1 git.master log-nopager --oneline
  trace: exec: 'git-log-nopager' '--oneline'
  trace: run_command: 'git-log-nopager' '--oneline'
  trace: run_command: 'git --no-pager log' '--oneline'
  trace: exec: 'sh' '-c' 'git --no-pager log "$@"' 'git --no-pager log' '--oneline'
  trace: built-in: git 'log' '--oneline'
  93c7d44 foo

  $ GIT_TRACE=1 git.jch.shell-alias log-nopager --oneline
  trace: exec: 'git-log-nopager' '--oneline'
  trace: run_command: 'git-log-nopager' '--oneline'
  trace: run_command: 'sh' '-c' 'git --no-pager log' '-' '--oneline'
  trace: exec: 'sh' '-c' 'git --no-pager log' '-' '--oneline'
  trace: built-in: git 'log'
  commit 93c7d44635e8bb56a4fd864d024ce75a2ad4ffcf
  Author: Jeff King <peff@xxxxxxxx>
  Date:   Tue Mar 22 06:57:02 2011 -0400

      foo

I think the evolution of the alias code was something like:

 1. Let's have alias.foo, so that "git foo XXX" can be aliased to "git
    log --whatever XXX", just like shell aliases.

 2. Oops, git doesn't allow some things in (1) that we might want to do,
    like turning off the pager or choosing a new repo. For that we need
    to respawn git, so now we have "!git --whatever1 log --whatever2".
    It appends the arguments, just like the form in (1), so it is
    consistent.

 3. Oops, (2) doesn't allow complex mini-scripts that access the
    parameters in a non-sequential way. You have to do "!sh -c 'git
    --whatever $1 log --whatever2 $2'".

Knowing that step (3) exists, I think your solution is a better one. The
question is whether it is better enough to be worth breaking the people
who were helped by step (2).

Another way of looking at it is that types (1) and (2) are like shell
aliases. And they suck for complex things, just the way that shell
aliases do. The solution in the shell is to put your complex alias into
a shell function, or to push it into its own script. In git, you can
push things into their own script, but we have no equivalent to a shell
function. So one solution is:

  git config function.silly '!echo hello $1; echo $# args, bye!'

The name is of course terrible. But I think the idea is sound that there
are two different types of interface people may want. On the other hand,
this is getting kind of grossly complex. The separate script option is
always available.

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]