Git alias with positional parameters

前端 未结 7 1063
北荒
北荒 2020-11-22 12:35

Basically I\'m trying to alias:

git files 9fa3

...to execute the command:

git diff --name-status 9fa3^ 9fa3
7条回答
  •  时光说笑
    2020-11-22 13:21

    Just bumped into something similar; hope it's oK to post my notes. One thing that confuses me about git aliases with arguments, probably comes from the git help config (I have git version 1.7.9.5):

    If the alias expansion is prefixed with an exclamation point, it will be treated as a shell command. For example, defining "alias.new = !gitk --all --not ORIG_HEAD", the invocation "git new" is equivalent to running the shell command "gitk --all --not ORIG_HEAD". Note that shell commands will be executed from the top-level directory of a repository, which may not necessarily be the current directory. [...]

    The way I see it - if an alias "will be treated as a shell command" when prefixed with exclamation point - why would I need to use a function, or sh -c with arguments; why not just write my command as-is?

    I still don't know the answer - but I think actually there is a slight difference in outcome. Here's a little test - throw this in your .git/config or your ~/.gitconfig:

    [alias]
      # ...
      ech = "! echo rem: "
      shech = "! sh -c 'echo rem:' "
      fech = "! f() { echo rem: ; }; f " # must have ; after echo!
      echargs = "! echo 0[[\"$0\"]] 1-\"$1\"/ A-"$@"/ "
      fechargs = "! f() { echo 0[[\"$0\"]] 1-\"$1\"/ A-"$@"/ ; }; f "
    

    Here is what I get running these aliases:

    $ git ech word1 word2
    rem: word1 word2
    
    $ git shech word1 word2
    rem:
    
    $ git fech word1 word2
    rem:
    
    $ git echargs word1 word2
    0[[ echo 0[["$0"]] 1-"$1"/ A-$@/ ]] 1-word1/ A-word1 word2/ word1 word2
    
    $ git fechargs word1 word2
    0[[ f() { echo 0[["$0"]] 1-"$1"/ A-$@/ ; }; f ]] 1-word1/ A-word1 word2/
    

    ... or: when you're using a "plain" command after the ! "as-is" in a git alias - then git automatically appends the arguments list to that command! A way to avoid it, is indeed, to call your script as either a function - or as argument to sh -c.

    Another interesting thing here (for me), is that in a shell script, one typically expects the automatic variable $0 to be the filename of the script. But for a git alias function, the $0 argument is, basically, the content of the entire string specifying that command (as entered in the config file).

    Which is why, I guess, if you happen to misquote - in the below case, that would be escaping the outer double quotes:

    [alias]
      # ...
      fail = ! \"echo 'A' 'B'\"
    

    ... - then git would fail with (for me, at least) somewhat cryptic message:

    $ git fail
     "echo 'A' 'B'": 1: echo 'A' 'B': not found
    fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory
    

    I think, since git "saw" a whole string as only one argument to ! - it tried to run it as an executable file; and correspondingly it failed finding "echo 'A' 'B'" as a file.

    In any case, in context of the git help config quote above, I'd speculate that it's more accurate to state something like: " ... the invocation "git new" is equivalent to running the shell command "gitk --all --not ORIG_HEAD $@", where $@ are the arguments passed to the git command alias from command line at runtime. ... ". I think that would also explain, why the "direct" approach in OP doesn't work with positional parameters.

提交回复
热议问题