Fondamentalement, j'essaie d'alias:
git files 9fa3
... pour exécuter la commande:
git diff --name-status 9fa3^ 9fa3
mais git ne semble pas transmettre de paramètres de position à la commande d'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 puis-je faire fonctionner cela?
$1
devrait fonctionner).Réponses:
La façon la plus évidente est d'utiliser une fonction shell:
Un alias sans
!
est traité comme une commande Git; par exemplecommit-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
Parce que les commandes sont exécutées à la racine du référentiel, vous pouvez utiliser une
${GIT_PREFIX}
variable lorsque vous vous référez aux noms de fichiers dans les commandesla source
!
est traité comme une commande Git; par exemplecommit-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.!
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 que vous attendez.Vous pouvez également référencer
sh
directement (au lieu de créer une fonction):(Notez le tiret à la fin de la ligne - vous en aurez besoin.)
la source
sh
, car il s'agit en soi d'un shell, et il est disponible sur la grande majorité des systèmes. L'utilisation du shell par défaut ne fonctionne que si la commande fonctionne comme écrite pour tous les shells.--
de-
car il est plus familier et moins susceptibles de stdin accidentellement moyenne à un moment donné. ("Un argument de - équivaut à -" dans bash (1) est invariable)sh -c
) est également inutile. Voir ma réponse pour une alternative.L'alias que vous recherchez est:
Avec validation d'argument:
La finale
#
est importante - elle empêche tous les arguments fournis par l'utilisateur d'être traités par le shell (il les commente).Remarque:
git
place tous les arguments fournis par l'utilisateur à la fin de la ligne de commande. Pour voir cela en action, essayez:GIT_TRACE=2 git files a b c d
Les guillemets échappés (en raison de l'imbrication) sont importants pour les noms de fichiers contenant des espaces ou
"; rm -rf --no-preserve-root /;
)la source
!
implique déjàsh -c
(affiché lors de l'ajoutGIT_TRACE=2
), il n'est donc pas nécessaire d'exécuter un autre sous-shell. Quels problèmes voyez-vous dans des cas plus compliqués?fp = "! 1=${1:-$(git headBranch)}; 2=${2:-up}; git fetch -fu $2 pull/$1/head:$1; git checkout $1; git branch -u $2 #"
. Cela fonctionne très bien sans les deux premières déclarations, mais tombe en panne si vous les utilisez. (MoiheadBranch = symbolic-ref --short HEAD
aussi).fp = "! a=${1:-$(git headBranch)}; b=${2:-up}; git fetch -fu $b pull/$a/head:$a; git checkout $a; git branch -u $b #"
."
devis sont requis?Utilisez GIT_TRACE = 1 décrit sur la page de manuel git pour rendre le traitement d'alias transparent:
Vos commandes originales fonctionnent avec la version 1.8.3.4 de git (Eimantas a noté que cela avait changé dans 1.8.2.1).
Les
sh -c '..' --
et lesf() {..}; f
options à la fois gérer proprement les paramètres « $ @ » de différentes façons (voir avec GIT_TRACE). L'ajout de "#" à un alias permettrait également des paramètres de position sans quitter les derniers.la source
files = "!git diff --name-status $1^ $1 #"
files = "!git diff --name-status $1^"
Comme indiqué par Drealmer ci - dessus :
GIT_PREFIX
étant défini par git dans le sous-répertoire dans lequel vous vous trouvez, vous pouvez contourner cela en changeant d'abord le répertoire:la source
cd ${GIT_PREFIX:-.} &&.
" (source: stackoverflow.com/a/21929373/266309 )!cd "${GIT_PREFIX:-.}" && ls -al
Je voulais faire ça avec un alias qui fait ça:
Au final, j'ai créé un script shell nommé git-m qui a ce contenu:
Cela a l'avantage d'être beaucoup plus lisible car il est sur plusieurs lignes. De plus, j'aime pouvoir appeler bash avec
-x
etset -e
. Vous pouvez probablement faire tout cela comme un alias, mais ce serait super laid et difficile à maintenir.Parce que le fichier est nommé,
git-m
vous pouvez l'exécuter comme ceci:git m foo bar
la source
'!f() { : git branch ; ... }; f'
et il remplira automatiquement l'alias en tant que branche, ce qui est très pratique..bashrc
fichier que je source. Mais je ne pense pas que je change la façon dont je complète automatiquement les arguments d'un script autant que le script lui-même, et ce ne serait que pendant le développement.Je suis juste tombé sur quelque chose de similaire; j'espère que c'est ok pour poster mes notes. Une chose qui me confond à propos des
git
alias avec des arguments, vient probablement degit help config
(j'ai la version 1.7.9.5 de git):La façon dont je le vois - si un alias "sera traité comme une commande shell" lorsqu'il est préfixé avec 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'il y a en fait une légère différence de résultat. Voici un petit test - jetez-le dans votre
.git/config
ou votre~/.gitconfig
:Voici ce que j'obtiens en exécutant ces alias:
... ou: lorsque vous utilisez une commande "ordinaire" après le
!
"tel quel" dans ungit
alias - puisgit
ajoute automatiquement la liste des arguments à cette commande! Un moyen de l'éviter est en effet d'appeler votre script soit comme une fonction, soit comme argument desh -c
.Une autre chose intéressante ici (pour moi), c'est que dans un script shell, on s'attend généralement à ce que la variable automatique
$0
soit le nom de fichier du script. Mais pour unegit
fonction d'alias, l'$0
argument est, fondamentalement, le contenu de la chaîne entière spécifiant cette commande (telle qu'elle est entrée dans le fichier de configuration).C'est pourquoi, je suppose, si vous vous trompez - dans le cas ci-dessous, cela échapperait aux doubles guillemets externes:
... -
git
échouerait alors avec (pour moi, au moins) un message quelque peu cryptique:Je pense que, puisque
git
"vu" une chaîne entière comme un seul argument à!
- il a essayé de l'exécuter comme un fichier exécutable; et en conséquence, il n'a pas réussi à trouver"echo 'A' 'B'"
un fichier.Dans tous les cas, dans le contexte de la
git help config
citation ci-dessus, je suppose qu'il est plus précis de dire quelque chose comme: " ... l'invocation" git new "équivaut à exécuter la commande shell" gitk --all --not ORIG_HEAD $ @ ", où $ @ sont les arguments passés à l'alias de commande git depuis la ligne de commande lors de l'exécution. ... ". Je pense que cela expliquerait également pourquoi l'approche "directe" dans OP ne fonctionne pas avec les paramètres de position.la source
fail
essaie d'exécuter une commande appelée "echo 'A' 'B" (c'est-à-dire 10 caractères). Même erreursh -c "'echo a b'"
et même cause, trop de couches de guillemets