Apenas esbarrei em algo semelhante; espero que esteja tudo bem em publicar minhas anotações. Uma coisa que me confunde sobre git
aliases com argumentos, provavelmente vem do git help config
(eu tenho a versão 1.7.9.5 do git):
Se a expansão do alias for prefixada com um ponto de exclamação, ela será tratada como um comando shell. Por exemplo, definindo "alias.new =! Gitk --all --not ORIG_HEAD", a chamada "git new" é equivalente a executar o comando do shell "gitk --all --not ORIG_HEAD". Observe que os comandos do shell serão executados no diretório de nível superior de um repositório, que pode não ser necessariamente o diretório atual. [...]
Do jeito que eu vejo - se um apelido "será tratado como um comando de shell" quando prefixado com ponto de exclamação - por que eu precisaria usar uma função ou sh -c
com argumentos; por que não apenas escrever meu comando como está?
Ainda não sei a resposta - mas acho que, na verdade, há uma pequena diferença no resultado. Aqui está um pequeno teste - jogue isso no seu .git/config
ou no seu ~/.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 "
Aqui está o que eu recebo executando esses 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/
... ou: quando você estiver usando um comando "simples" após o !
"no estado em que está" em um git
alias - git
anexará automaticamente a lista de argumentos a esse comando! Uma maneira de evitá-lo é chamar seu script como uma função - ou como argumento sh -c
.
Outra coisa interessante aqui (para mim) é que, em um script de shell, normalmente se espera que a variável automática $0
seja o nome do arquivo do script. Mas para uma git
função de alias, o $0
argumento é, basicamente, o conteúdo de toda a cadeia que especifica esse comando (conforme digitado no arquivo de configuração).
Por isso, eu acho, se você citar incorretamente - no caso abaixo, isso estaria escapando das aspas duplas externas:
[alias]
# ...
fail = ! \"echo 'A' 'B'\"
... - então git
falharia com (pelo menos para mim) a mensagem um tanto enigmática:
$ git fail
"echo 'A' 'B'": 1: echo 'A' 'B': not found
fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory
Eu acho que, uma vez que git
"via" uma string inteira como apenas um argumento para !
- tentava executá-la como um arquivo executável; e correspondentemente falhou ao encontrar "echo 'A' 'B'"
como um arquivo.
De qualquer forma, no contexto da git help config
citação acima, eu especularia que é mais preciso afirmar algo como: " ... a invocação" git new "é equivalente a executar o comando shell" gitk --all --not ORIG_HEAD $ @ ", onde $ @ são os argumentos passados para o alias do comando git na linha de comando no tempo de execução. ... ". Eu acho que isso também explicaria por que a abordagem "direta" no OP não funciona com parâmetros posicionais.
$1
deve funcionar).