Git alias con parameters posicionales

Básicamente estoy tratando de alias:

git files 9fa3 

… para ejecutar el command:

 git diff --name-status 9fa3^ 9fa3 

pero git no parece pasar los parameters posicionales al command 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 abcde edcba 

… ¿cómo puedo hacer que esto funcione?

La forma más obvia es usar una function de shell:

 [alias] files = "!f() { git diff --name-status \"$1^\" \"$1\"; }; f" 

Un alias sin ! se trata como un command Git; por ejemplo, commit-all = commit -a .

Con el ! , se ejecuta como su propio command en el caparazón, lo que le permite utilizar una magia más fuerte como esta.

También puede hacer reference a sh directamente (en lugar de crear una function):

 [alias] files = !sh -c 'git diff --name-status $1^ $1' - 

(Tenga en count el guión al final de la línea; lo necesitará).

El alias que está buscando es:

 files = "!git diff --name-status \"$1\"^ \"$1\" #" 

Con la validation de arguments:

 files = "![ x$# != x1 ]&&echo "commit-ish requinetworking" >&2 || git diff --name-status \"$1\"^ \"$1\" #" 

El # final es importante: evita que todos los arguments suministrados por el usuario sean procesados ​​por el shell (los comenta).

Nota: git coloca todos los arguments proporcionados por el usuario al final de la línea de command. Para ver esto en acción, intente: GIT_TRACE=2 git files abcd

Las citas escapadas (debido a la anidación) son importantes para los nombres de files que contienen espacios o "; rm -rf --no-preserve-root /; )

Use GIT_TRACE = 1 descrito en la página man de git para hacer que el process de alias sea transparente:

 $ git config alias.files !git diff --name-status $1^ $1 $ GIT_TRACE=1 git files 1d49ec0 trace: exec: 'git-files' '1d49ec0' trace: run_command: 'git-files' '1d49ec0' trace: run_command: 'git diff --name-status $1^ $1' '1d49ec0' trace: exec: '/bin/sh' '-c' 'git diff --name-status $1^ $1 "$@"' 'git diff --name-status $1^ $1' '1d49ec0' trace: built-in: git 'diff' '--name-status' '1d49ec0^' '1d49ec0' '1d49ec0' trace: run_command: 'less -R' trace: exec: '/bin/sh' '-c' 'less -R' 'less -R' MM TODO 

Tus commands originales funcionan con la versión 1.8.3.4 de git (Eimantas notó que esto cambió en 1.8.2.1).

El sh -c '..' -- y f() {..}; f f() {..}; f opciones f() {..}; f manejan limpiamente los parameters "$ @" de diferentes maneras (ver con GIT_TRACE). Agregar "#" a un alias también permitiría los parameters posicionales sin abandonar los posteriores.

Según lo declarado por Drealmer arriba ( http://sofes.miximages.com/a/3322412/2955802 )

" Ten cuidado, ! se ejecutará en la raíz del repository, por lo que el uso de routes relativas al llamar a su alias no dará los resultados que podría esperar. – Drealmer 8 de agosto de 13 a 16:28 »

Git_PREFIX establecido por git en el subdirectory en el que se encuentra, puede eludir esto cambiando primero el directory:

git alias ls = '! cd $ {GIT_PREFIX: -.}; ls -al '

Quería hacer esto con un alias que hace esto:

 git checkout $1; git merge --ff-only $2; git branch -d $2; 

Al final, creé un script de shell llamado git-m que tiene este contenido:

 #!/bin/bash -x set -e #by naming this git-m and putting it in your PATH, git will be able to run it when you type "git m ..." if [ "$#" -ne 2 ] then echo "Wrong number of arguments. Should be 2, was $#"; exit 1; fi git checkout $1; git merge --ff-only $2; git branch -d $2; 

Esto tiene el beneficio de que es mucho más legible porque está en múltiples líneas. Además, me gusta poder llamar a bash con -x y set -e . Probablemente puedas hacer todo esto como un alias, pero sería súper feo y difícil de mantener.

Como el file se llama git-m , puede ejecutarlo así: git m foo bar

Simplemente tropecé con algo similar; Espero que sea bueno para publicar mis notas. Una cosa que me confunde con los alias de git con arguments, probablemente proviene de la git help config (tengo la versión de Git 1.7.9.5):

Si la expansión de alias está precedida por un signo de exclamación, se tratará como un command de shell. Por ejemplo, al definir "alias.new =! Gitk –all –n ORIG_HEAD", la invocación "git new" es equivalente a ejecutar el command de shell "gitk –all –n ORIG_HEAD". Tenga en count que los commands de shell se ejecutarán desde el directory de nivel superior de un repository, que puede no ser necesariamente el directory actual. […]

Tal como lo veo, si un alias "se tratará como un command de shell" cuando se le agrega un signo de exclamación, ¿por qué necesitaría usar una function, o sh -c con arguments? ¿por qué no simplemente escribir mi command tal como está?

Todavía no sé la respuesta, pero creo que en realidad hay una ligera diferencia en el resultado. Aquí hay una pequeña testing: eche esto en su .git/config o su ~/.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-"$@"/ " datergs = "! 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 datergs word1 word2 0[[ f() { echo 0[["$0"]] 1-"$1"/ A-$@/ ; }; f ]] 1-word1/ A-word1 word2/ 

… o: cuando estás usando un command "simple" después de ! "como está" en un git alias – ¡entonces git agrega automáticamente la list de arguments a ese command! Una forma de evitarlo es, de hecho, llamar a su secuencia de commands como una function, o como un argumento para sh -c .

Otra cosa interesante aquí (para mí) es que, en un script de shell, uno típicamente espera que la variable automática $0 sea ​​el nombre de file del script. Pero para una function de git alias, el argumento $0 es, básicamente, el contenido de la cadena completa que especifica ese command (tal como se ingresó en el file de configuration).

Por eso, supongo, si citas mal – en el caso de abajo, eso escapingía a las comillas dobles externas:

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

… – entonces git fallaría con (para mí, al less) post 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 git "vio" una cadena completa como un solo argumento ! – intentó ejecutarlo como un file ejecutable; y correspondientemente falló al encontrar "echo 'A' 'B'" como un file.

En cualquier caso, en el context de la cita de git help config anterior, especularía que es más exacto decir algo como: " … la invocación" git new "es equivalente a ejecutar el command de shell" gitk –all – -no ORIG_HEAD $ @ ", donde $ @ son los arguments pasados ​​al alias del command git desde la command-line en el time de ejecución … ". Creo que eso también explicaría por qué el enfoque "directo" en OP no funciona con parameters posicionales.