299 votes

Alias Git avec paramètres positionnels

En fait, j'essaie de créer un alias :

git files 9fa3

...pour exécuter la commande :

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

mais git ne semble pas passer de paramètres positionnels à la commande alias. J'ai essayé :

[alias]
    files = "!git diff --name-status $1^ $1"
    files = "!git diff --name-status {1}^ {1}"

...et quelques autres, mais ça n'a pas marché.

Le cas dégénéré serait :

$ git echo_reverse_these_params a b c d e
e d c b a

...comment faire pour que ça marche ?

22 votes

Notez que dans git 1.8.2.1, il est possible de faire cela sans fonction shell (votre approche originale avec $1 devrait fonctionner).

10 votes

@Eimantas Souhaitez-vous développer dans une réponse ? Cela ne fonctionne pas pour moi, et je ne trouve aucune documentation à ce sujet.

1 votes

@Eimantas il n'y a rien à propos de cela dans la notes de mise à jour cependant.

425voto

Jefromi Points 127932

Une fonction shell pourrait être utile à cet égard :

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

Un alias sans ! est traitée comme une commande Git ; par exemple commit-all = commit -a .

Avec le ! il est exécuté comme sa propre commande dans le shell, vous permettant d'utiliser une magie plus forte comme celle-ci.

UPD
Comme les commandes sont exécutées à la racine du référentiel, vous pouvez utiliser ${GIT_PREFIX} lorsqu'on se réfère aux noms de fichiers dans les commandes.

9 votes

Merci, cela semble tout à fait correct : [alias] files = "!f() { echo $3 $2 $1 ; } ; f" ; $ git files a b c => c b a

0 votes

@jefromi @mipadi Je ne suis pas un rédacteur de shell script ; pouvez-vous nous expliquer pourquoi les ! est nécessaire au début de la définition de la fonction ? Merci !

1 votes

@KohányiRóbert : Ce n'est en fait pas une question de shell script ; c'est une particularité de la configuration de git. Un alias sans ! est traitée comme une commande Git ; par exemple commit-all = commit -a . Avec le ! il est exécuté comme sa propre commande dans le shell, vous permettant d'utiliser une magie plus forte comme celle-ci.

105voto

mipadi Points 135410

Vous pouvez également faire référence à sh directement (au lieu de créer une fonction) :

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

(Notez le tiret à la fin de la ligne - vous en aurez besoin).

1 votes

...y a-t-il des avantages tangibles par rapport à la réponse de jefromi ? Je veux dire : la fonction def dans sa réponse est "alias-local" et signifie que vous n'avez pas bash qui appelle bash, n'est-ce pas ? Dans tous les cas, merci pour cette implémentation alternative.

0 votes

Je ne pense pas que l'une ou l'autre solution présente des avantages par rapport à l'autre - ce sont simplement deux façons différentes de faire la même chose.

0 votes

Je pense que la solution de jefromi est meilleure si vous voulez partager les alias, ou utiliser plusieurs shells ; et si sh n'appelle pas votre shell actuel ?

32voto

bsb Points 515

Utilisez GIT_TRACE=1 décrit sur la page de manuel git pour rendre le traitement des alias transparent :

$ 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

Vos commandes originales fonctionnent avec la version 1.8.3.4 de git (Eimantas a noté que cela a changé en 1.8.2.1).

Le site sh -c '..' -- et f() {..}; f Les deux options traitent proprement les paramètres "$@" de différentes manières (voir avec GIT_TRACE). L'ajout de "#" à un alias permettrait également de prendre en compte les paramètres positionnels sans laisser les paramètres de fin de ligne.

1 votes

Merci pour les explications : ces commandes fonctionnent pour moi sur le problème original, en suivant vos conseils : files = "!git diff --name-status $1^ $1 #" files = "!git diff --name-status $1^"

20voto

Comme indiqué par Drealmer au-dessus de :

" Attention, ! s'exécutera à la Racine du référentiel, donc l'utilisation de chemins relatifs lors de l'appel de votre alias ne donnera pas les résultats escomptés. - Drealmer Aug 8 '13 at 16:28 "

GIT_PREFIX étant défini par git comme le sous-répertoire dans lequel vous vous trouvez, vous pouvez contourner ce problème en changeant d'abord le répertoire :

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

0 votes

J'ai également des problèmes avec cela (les commandes sont exécutées à la racine du référentiel) mais cette solution ne semble rien faire. (Si cela a de l'importance, j'utilise OS X).

0 votes

Oups... git alias est un alias que j'ai créé.

0 votes

(depuis git 1.8.2) git config --set alias.alias = ' ! git config --global alias.$1 "$2"''.

7voto

sdaau Points 6262

Je viens de tomber sur un sujet similaire ; j'espère que je peux poster mes notes. Une chose qui me rend confus à propos de git alias avec des arguments, vient probablement de l' git help config (J'ai la version 1.7.9.5 de git) :

Si l'expansion de l'alias est préfixée d'un point d'exclamation, elle sera traitée comme une commande shell. Par exemple, en définissant "alias.new = !gitk --all --not ORIG_HEAD", l'invocation de "git new" est équivalente à l'exécution de la commande shell "gitk --all --not ORIG_HEAD". Notez que les commandes shell seront exécutées depuis le répertoire de premier niveau d'un référentiel, qui n'est pas nécessairement le répertoire courant. [...]

De la manière dont je le vois - si un alias "sera traité comme une commande shell" lorsqu'il est préfixé par un point d'exclamation - pourquoi aurais-je besoin d'utiliser une fonction, ou sh -c avec des arguments ; pourquoi ne pas simplement écrire ma commande telle quelle ?

Je ne connais toujours pas la réponse - mais je pense qu'en fait, il y a une légère différence dans le résultat. Voici un petit test - mettez ceci dans votre ordinateur. .git/config ou votre ~/.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 "

Voici ce que j'obtiens en utilisant ces 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/

... ou : lorsque vous utilisez une commande "simple" après l'option ! "tel quel" dans un git alias - alors git ajoute automatiquement la liste des arguments à cette commande ! Une façon d'éviter cela, est en effet, d'appeler votre script comme une fonction - ou comme argument à la commande sh -c .

Une autre chose intéressante ici (pour moi), est que dans un shell script, on s'attend typiquement à la variable automatique $0 pour être le nom de fichier du script. Mais pour un git la fonction alias, la $0 L'argument est, fondamentalement, le contenu de la tout le site chaîne de caractères spécifiant cette commande (telle que saisie dans le fichier de configuration).

C'est pourquoi, je suppose, si vous faites une erreur de citation - dans le cas ci-dessous, il s'agirait d'échapper aux guillemets extérieurs :

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

... - alors git échouerait avec (pour moi, du moins) un message quelque peu cryptique :

$ git fail
 "echo 'A' 'B'": 1: echo 'A' 'B': not found
fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory

Je pense que, depuis git "a vu" une chaîne entière comme un seul argument à ! - il a essayé de l'exécuter comme un fichier exécutable, et par conséquent il n'a pas réussi à trouver "echo 'A' 'B'" comme un fichier.

En tout cas, dans le contexte de la git help config Dans le cas de la citation ci-dessus, je pense qu'il est plus exact d'affirmer quelque chose comme : " ... l'invocation "git new" est équivalente à l'exécution de la commande shell "gitk --all --not ORIG_HEAD $@", où $@ sont les arguments passés à l'alias de la commande git depuis la ligne de commande au moment de l'exécution. ... ". Je pense que cela expliquerait également pourquoi l'approche "directe" du PO ne fonctionne pas avec les paramètres de position.

0 votes

Un bon test. Un moyen rapide de vérifier toutes les possibilités !

0 votes

fail essaie d'exécuter une commande appelée "echo 'A' 'B" (c'est-à-dire de 10 caractères). Même erreur de sh -c "'echo a b'" et même cause, trop de couches de citations

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X