Básicamente estoy tratando de alias:
git files 9fa3
... para ejecutar el comando:
git diff --name-status 9fa3^ 9fa3
pero git no parece pasar parámetros posicionales al comando alias. Yo he tratado:
[alias]
files = "!git diff --name-status $1^ $1"
files = "!git diff --name-status {1}^ {1}"
... y algunos otros pero esos no funcionaron.
El caso degenerado sería:
$ git echo_reverse_these_params a b c d e
e d c b a
... ¿Cómo puedo hacer que esto funcione?
$1
debería funcionar).Respuestas:
La forma más obvia es usar una función de shell:
Un alias sin
!
se trata como un comando Git; por ejcommit-all = commit -a
.Con el
!
, se ejecuta como su propio comando en el shell, lo que le permite usar magia más fuerte como esta.UPD
Debido a que los comandos se ejecutan en la raíz del repositorio, puede usar
${GIT_PREFIX}
variables al referirse a los nombres de archivo en los comandosfuente
!
se trata como un comando Git; por ejcommit-all = commit -a
. Con el!
, se ejecuta como su propio comando en el shell, lo que le permite usar magia más fuerte como esta.!
se ejecutará en la raíz del repositorio, por lo que el uso de rutas relativas al llamar a su alias no le dará los resultados que puede esperar.También puede hacer referencia
sh
directamente (en lugar de crear una función):(Tenga en cuenta el guión al final de la línea; lo necesitará).
fuente
sh
, ya que es en sí mismo un shell y está disponible en la gran mayoría de los sistemas. El uso del shell predeterminado solo funciona si el comando funciona como está escrito para todos los shells.--
a-
, ya que es más familiar y menos propensos a la entrada estándar accidentalmente media en algún momento. ("Un argumento de - es equivalente a -" en bash (1) es ingoogleable)sh -c
) también es innecesario. Vea mi respuesta para una alternativa.El alias que estás buscando es:
Con validación de argumento:
El final
#
es importante: evita que el shell procese todos los argumentos proporcionados por el usuario (los comenta).Nota:
git
coloca todos los argumentos proporcionados por el usuario al final de la línea de comando. Para ver esto en acción, intente:GIT_TRACE=2 git files a b c d
Las comillas escapadas (debido a la anidación) son importantes para los nombres de archivo que contienen espacios o
"; rm -rf --no-preserve-root /;
)fuente
!
ya implicash -c
(se muestra al anteponerGIT_TRACE=2
), por lo que no hay necesidad de ejecutar otro sub-shell. ¿Qué problemas ves en casos más complicados?fp = "! 1=${1:-$(git headBranch)}; 2=${2:-up}; git fetch -fu $2 pull/$1/head:$1; git checkout $1; git branch -u $2 #"
. Esto funciona muy bien sin las dos primeras declaraciones, pero se cae si las usa. (YoheadBranch = symbolic-ref --short HEAD
también).fp = "! a=${1:-$(git headBranch)}; b=${2:-up}; git fetch -fu $b pull/$a/head:$a; git checkout $a; git branch -u $b #"
."
se requieren cotizaciones?Use GIT_TRACE = 1 descrito en la página de manual de git para hacer que el procesamiento de alias sea transparente:
Sus comandos originales funcionan con git versión 1.8.3.4 (Eimantas notó que esto cambió en 1.8.2.1).
Las opciones
sh -c '..' --
yf() {..}; f
manejan limpiamente los parámetros "$ @" de diferentes maneras (ver con GIT_TRACE). Agregar "#" a un alias también permitiría parámetros posicionales sin dejar los finales.fuente
files = "!git diff --name-status $1^ $1 #"
files = "!git diff --name-status $1^"
Como lo indicó Drealmer anteriormente :
GIT_PREFIX
siendo establecido por git en el subdirectorio en el que se encuentra, puede evitar esto cambiando primero el directorio:fuente
cd ${GIT_PREFIX:-.} &&.
" (fuente: stackoverflow.com/a/21929373/266309 )!cd "${GIT_PREFIX:-.}" && ls -al
Quería hacer esto con un alias que haga esto:
Al final, creé un script de shell llamado git-m que tiene este contenido:
Esto tiene el beneficio de que es mucho más legible porque está en varias líneas. Además, me gusta poder llamar a bash con
-x
yset -e
. Probablemente puedas hacer todo esto como un alias, pero sería muy feo y difícil de mantener.Debido a que el archivo tiene un nombre
git-m
, puede ejecutarlo así:git m foo bar
fuente
'!f() { : git branch ; ... }; f'
y completará automáticamente el alias como una rama que es muy útil..bashrc
estoy en mi archivo. Pero no creo que cambie la forma en que autocompleto los argumentos a un script tanto como al script en sí, y solo será durante el desarrollo.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 degit help config
(tengo git versión 1.7.9.5):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
:Esto es lo que obtengo al ejecutar estos alias:
... o: cuando está usando un comando "simple" después del
!
"como está" en ungit
alias, ¡entoncesgit
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 hacerlosh -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 unagit
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:
... - entonces
git
fallaría con (al menos para mí) un mensaje algo críptico: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.fuente
fail
está intentando ejecutar un comando llamado "echo 'A' 'B" (es decir, 10 caracteres de longitud). El mismo errorsh -c "'echo a b'"
y la misma causa, demasiadas capas de citas