Acabo de toparme con algo similar; Espero que esté bien publicar mis notas. Una cosa que me confunde sobre los git
alias con argumentos, probablemente proviene de git help config
(tengo git versión 1.7.9.5):
Si la expansión del alias tiene el prefijo de un signo de exclamación, se tratará como un comando de shell. Por ejemplo, al definir "alias.new =! Gitk --all --not ORIG_HEAD", la invocación "git new" es equivalente a ejecutar el comando de shell "gitk --all --not ORIG_HEAD". Tenga en cuenta que los comandos de shell se ejecutarán desde el directorio de nivel superior de un repositorio, que puede no ser necesariamente el directorio actual. [...]
A mi modo de ver, si un alias "se tratará como un comando de shell" cuando se prefija con un signo de exclamación, ¿por qué necesitaría usar una función o sh -c
con argumentos? ¿Por qué no escribir mi comando tal cual?
Todavía no sé la respuesta, pero creo que en realidad hay una ligera diferencia en el resultado. Aquí hay una pequeña prueba: pon esto en tu .git/config
o en tu ~/.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 "
Esto es lo que obtengo al ejecutar estos alias:
$ 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/
... o: cuando está usando un comando "simple" después del !
"como está" en un git
alias, ¡entonces git
automáticamente agrega la lista de argumentos a ese comando! Una forma de evitarlo es llamar a su script como una función o como un argumento para hacerlo sh -c
.
Otra cosa interesante aquí (para mí), es que en un script de shell, uno normalmente espera que la variable automática $0
sea el nombre del archivo del script. Pero para una git
función de alias, el $0
argumento es, básicamente, el contenido de toda la cadena que especifica ese comando (como se ingresó en el archivo de configuración).
Por eso, supongo, si sucede una cita errónea, en el siguiente caso, eso sería escapar de las comillas dobles externas:
[alias]
# ...
fail = ! \"echo 'A' 'B'\"
... - entonces git
fallaría con (al menos para mí) un mensaje algo críptico:
$ git fail
"echo 'A' 'B'": 1: echo 'A' 'B': not found
fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory
Creo que, dado que git
"vio" una cadena completa como un solo argumento !
, intentó ejecutarla como un archivo ejecutable; y correspondientemente no se pudo encontrar "echo 'A' 'B'"
como un archivo.
En cualquier caso, en el contexto de la git help config
cita anterior, especularía que es más preciso decir algo como: " ... la invocación" git new "es equivalente a ejecutar el comando de shell" gitk --all --not ORIG_HEAD $ @ ", donde $ @ son los argumentos pasados al alias del comando git desde la línea de comandos en tiempo de ejecución ... ". Creo que eso también explicaría por qué el enfoque "directo" en OP no funciona con parámetros posicionales.
$1
debería funcionar).