usar tag remote how hacer drop delete create como git command parameters position alias

remote - how to delete tag git



Git alias con parámetros posicionales. (7)

Básicamente estoy tratando de alias:

git files 9fa3

... para ejecutar el comando:

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

pero parece que git no pasa los 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?


Acabo de tropezar con algo similar; Espero que sea bueno para publicar mis notas. Una cosa que me confunde acerca de los alias de git con los argumentos, probablemente proviene de la git help config (tengo la versión 1.7.9.5 de git):

Si la expansión de alias tiene un prefijo con 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. [...]

La forma en que lo veo, 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 solo escribo mi orden 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 prueba: ~/.gitconfig 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-"$@"/ " fechargs = "! f() { echo 0[[/"$0/"]] 1-/"$1/"/ A-"$@"/ ; }; f "

Aquí es lo que me sale corriendo 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ás usando un comando "normal" después de ! "tal como está" en un alias de git - ¡entonces git agrega automáticamente la lista de argumentos a ese comando! Una forma de evitarlo es, de hecho, llamar a su script como una función, o como un argumento para 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 de archivo del script. Pero para una función de alias de git , el argumento de $0 es, básicamente, el contenido de toda la cadena que especifica ese comando (tal como se ingresó en el archivo de configuración).

Es por eso que, supongo, si se da una cita errónea, en el caso siguiente, se escaparía de las comillas dobles externas:

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

... - entonces git fallaría con (para mí, al menos) un mensaje un tanto 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, ya que git "vio" una cadena entera como solo un argumento para ! - trató de ejecutarlo como un archivo ejecutable; y, en consecuencia, no pudo encontrar "echo ''A'' ''B''" como archivo.

En cualquier caso, en el contexto de la cita de git help config anterior, yo especularía que es más exacto decir algo como: " ... la invocación" git new "es equivalente a ejecutar el comando de shell" gitk --all - -no ORIG_HEAD $ @ ", donde $ @ son los argumentos pasados ​​al alias de comando git desde la línea de comando 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.


El alias que buscas es:

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

Con validación de argumentos:

files = "!cd -- /"${GIT_PREFIX:-.}/" && [ x$# != x1 ] && echo commit-ish required >&2 || git diff --name-status /"$1/"^ /"$1/" #"

El # final es importante: evita que todos los argumentos proporcionados por el usuario sean procesados ​​por el shell (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 abcd

Las citas escapadas (debido al anidamiento) son importantes para los nombres de archivos que contienen espacios o "; rm -rf --no-preserve-root /; )


La forma más obvia es usar una función de shell:

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

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

Con el ! , se ejecuta como su propio comando en el shell, permitiéndote usar magia más fuerte como esta.

UPD
Debido a que los comandos se ejecutan en la raíz del repositorio, puede usar la variable ${GIT_PREFIX} cuando ${GIT_PREFIX} referencia a los nombres de archivo en los comandos


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 la ventaja de que es mucho más legible porque está en varias 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 muy feo y difícil de mantener.

Debido a que el archivo se llama git-m , puedes ejecutarlo así: git m foo bar


Según lo indicado por Drealmer above :

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

GIT_PREFIX configura GIT_PREFIX en el subdirectorio en el que se encuentra, puede evitarlo cambiando primero el directorio:

git config --global alias.ls ''! cd "$ {GIT_PREFIX: -.}"; ls -al ''


También puede hacer referencia a sh directamente (en lugar de crear una función):

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

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


Use GIT_TRACE = 1 descrito en la página de manual de git para que el procesamiento 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

Sus comandos 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 ambas manejan limpiamente los parámetros "$ @" de diferentes maneras (ver con GIT_TRACE). Agregar "#" a un alias también permitiría los parámetros posicionales sin dejar los finales.