Git Alias: múltiples comandos y parámetros

182

Estoy tratando de crear un alias que use múltiples comandos de Git y parámetros posicionales. Hay páginas de Stackoverflow para cada una, y parecería dolorosamente obvio hacer ambas cosas, pero estoy teniendo problemas.

Como ejemplo, quiero cambiar a branch foo y realizar un estado. Entonces en mi .gitconfig, tengo:

  [alias] 
     chs = !sh -c 'git checkout $0 && git status'

que no funciona Mientras que algo como esto funcionará.

chs = !sh -c 'git checkout $0'

echoes = !sh -c 'echo hi && echo bye'

Cualquier idea sería apreciada.

Stella
fuente
Mi alias: git config --global alias.go '! Git commit -a && git pull --rebase && git push && git status'. Nota: Use comillas simples.
Marcus Becker

Respuestas:

157

Esto funcionará (probado con zsh y bash):

[alias] chs = !git checkout $1 && git status
Olivier Verdier
fuente
1
No, no lo hará. Git se transformará git chs fooengit checkout && git status foo
Lily Ballard
24
Interesante, git en realidad completa las variables posicionales ahora en alias de shell. Pero todavía está roto, porque también los agrega como argumentos. Un alias de echo $1 && echo done, cuando se invoca con el argumento 'foo', generará tanto "foo" como "done foo".
Lily Ballard
77
¿Cuál es el signo de exclamación anterior para la primera invocación de git?
Elijah Lynn el
21
@ElijahLynn: en un alias git, un !medio principal pasa todo al shell. De lo contrario, supone que está intentando ejecutar otro comando git y lo pasa como argumentos al gitbinario.
Lily Ballard
2
@Brondahl Clever. Sin embargo, lo recomendaría en ;:lugar de && :. Y eso también funciona bien en Unix.
Lily Ballard
82

Esto apunta a Windows batch / msysgit bash; podría no funcionar en otros entornos.

Como han dicho Olivier Verdier y Lily Ballard

[alias] chs = !git checkout $1 && git status

casi funciona, pero da una inserción extra espuria del argumento ...

git chs demo -> git checkout demo && git status demo

Pero si agrega && :al final de su alias, el argumento falso se consume en una etiqueta de ubicación.

Entonces

[alias] chs = !git checkout $1 && git status && :

da la salida correcta ... git chs demo -> git checkout demo && git status

Brondahl
fuente
9
El && :es oro y hace que esta solución funcione para comandos donde el argumento adicional sería problemático.
Clay
3
@Clay (o cualquier otra persona) - ¿Podría alguien explicarle a BASH-desafiado qué && :hace?
Justin Morgan
77
@JustinMorgan && significa que si el comando anterior se convierte en 0 (éxito), ejecute el comando después de &&. ':', los dos puntos, es un comando integrado de shell, que no hace nada más que expandir argumentos y realizar redirecciones y devolver el estado 0. Aquí hay algunos usos: 1. a=123;$aerrores, pero a=123; : $ano lo hace. 2. : > hello.txtvacía hello.txt. 3. if [ "$a" = "hello" ];then : ;fifunciona bien pero errores sin ':'. Es como passen python. 4. : this is a comment, los dos puntos seguidos por el espacio funcionan como #en una línea de comentario.
ElpieKay
2
este es un truco ... git debería aceptar el modo de comando múltiple
kchoi
1
Gracias @ElpieKay por la explicación. Mi alias git local para un proyecto era co = !git checkout public/compiled && git checkout $1y cuando lo hiciera git co masterrecibiría el mensaje error: pathspec 'master' did not match any file(s) known to git.. No pensé que esta respuesta fuera útil para mí porque lo primero que menciona es Windows y estoy en Linux. Pero explicaste por qué.
Tyler Collier
73

Puede definir una función de shell.

[alias] chs = "!f(){ git checkout \"$1\" && git status; };f"
Lily Ballard
fuente
Vi esto en otra página de stackoverflow, pero mi terminal cygwin dice que la función no se reconoce cuando intento ejecutarla.
Stella
@Stella: dejé una cita de cierre allí que no es útil esta sintaxis del archivo de configuración. Asegúrate de no tenerlo.
Lily Ballard
2
Wow ... Desafortunadamente, todo esto fue un problema de versión. Estaba usando Git 1.7.3, y ninguno de estos métodos funcionó. Actualicé a 1.7.6 y listo, todo funcionó. ¡Gracias chicos!
Stella
55
si usa Windows, creo que debe rodear la definición de la función de shell con comillas dobles"
drzaus
44
La respuesta de Olivier no funcionó para mí usando parámetros (OSX). Esto funcionó perfectamente.
Ohad Schneider
25

Pude crear alias git de varias líneas y bastante complejos. Funcionan bien en Windows, pero supongo que también funcionarían en otro lugar, por ejemplo:

safereset = "!f() { \
                trap 'echo ERROR: Operation failed; return' ERR; \
                echo Making sure there are no changes...; \
                last_status=$(git status --porcelain);\
                if [[ $last_status != \"\" ]]; then\
                    echo There are dirty files:;\
                    echo \"$last_status\";\
                    echo;\
                    echo -n \"Enter Y if you would like to DISCARD these changes or W to commit them as WIP: \";\
                    read dirty_operation;\
                    if [ \"$dirty_operation\" == \"Y\" ]; then \
                        echo Resetting...;\
                        git reset --hard;\
                    elif [ \"$dirty_operation\" == \"W\" ]; then\
                        echo Comitting WIP...;\
                        git commit -a --message='WIP' > /dev/null && echo WIP Comitted;\
                    else\
                        echo Operation cancelled;\
                        exit 1;\
                    fi;\
                fi;\
            }; \
            f"

Escribí una publicación y tengo algunos ejemplos más aquí .

VitalyB
fuente
2
una mejora para esto sería agregar !f() { : resetpara obtener terminaciones del comando de reinicio github.com/git/git/blob/master/contrib/completion/…
un usuario
¡Gran trabajo! ¿Bajo qué licencia se publica ese artículo? ¿Te importaría si traduzco partes de él para StackOverflow en ruso?
Nick Volynkin
@NickVolynkin Lo siento por la respuesta tardía. Gracias y, por supuesto, adelante :)
VitalyB
22
[alias]
chs = !git branch && git status
FractalSpace
fuente
8
¿Para qué sirve !?
AutonomousApps
1
No pude encontrar el documento para el !pero, por lo que puedo ver, git supondrá de forma predeterminada que el alias es un comando git, por t = statuslo que funcionará. Sin embargo, si lo intentas t = git status, no funcionará (dirá el comando "git" no encontrado). Entonces, cuando !entra, le dice que ejecute el comando como si fuera un shell, y normalmente lo necesita cuando tiene múltiples comandos git por alias, por lo que puede tener, t = !git status && git logpor ejemplo, y funcionará.
Laurent
Aquí hay una pregunta de StackOverflow que trata con signos de exclamación (!) En alias Git: stackoverflow.com/questions/21083933/… .
Jacob Lockard
6

Prueba este:

[alias]
    chs = "!sh -c 'git checkout \"$0\" && git status'"

Llámalo así: git chs master

Brocksamson
fuente
6

Es posible tener un alias git multilínea agregando \al final de cada línea.

[alias] 
   chs = "!git checkout $1 \ 
          ; git status     \
         "
gmarik
fuente
2
¡Gracias! En realidad no tuve problemas "!git fetch --prune --all; git pull --rebase upstream master; git push origin master"para usar mi alias.
Droogans
3

El problema aquí es que los parámetros posicionales parecen estar siendo enviados al comando de shell dos veces (a partir de git 1.9.2). Para ver a qué me refiero, prueba esto:

[alias]
  test = !git echo $*

Entonces hazlo git test this is my testing string. Debe observar el siguiente resultado (las dos últimas líneas editadas aquí para mayor claridad):

03:41:24 (release) ~/Projects/iOS$ git test this is my testing string
this is my testing string this is my testing string
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
          #1                         #2

Una forma de evitar esto sería

[alias]
  chs = !git checkout $1 && git status && git echo x >/dev/null

Esto consumirá el parámetro posicional adicional a medida que se aplique a ese último comando de eco y no tendrá ningún efecto en los resultados.

Ben Collins
fuente