61 votes

Est-il possible de remplacer une commande git par un alias git ?

Mon ~/.gitconfig est :

[alias]
        commit = "!sh commit.sh"

Cependant, lorsque je tape git commit , script n'est pas appelé.

Est-ce possible, ou dois-je utiliser un autre nom d'alias ?

2 votes

La réponse de mathepic est tout à fait correcte. Bien sûr, je pense que c'est une question qui n'a pas lieu d'être. Tant qu'à faire un alias, pourquoi ne pas raccourcir la commande ? Alias co à !sh checkout.sh afin que vous n'ayez pas à tout taper (ou même à le compléter par tabulation).

0 votes

C'est regrettable. J'aurais également aimé que cette fonctionnalité remplace le comportement par défaut de "git log" par un format en ligne. Je sais qu'on peut utiliser d'autres alias mais tant que celui par défaut existe, l'habitude fait qu'on l'utilise et qu'on n'apprend jamais la commande de remplacement :(

51voto

alternative Points 7053

Ce n'est PAS POSSIBLE

Ceci provient de mon clone de git.git :

static int run_argv(int *argcp, const char ***argv)
{
    int done_alias = 0;

    while (1) {
        /* See if it's an internal command */
        handle_internal_command(*argcp, *argv);

        /* .. then try the external ones */
        execv_dashed_external(*argv);

        /* It could be an alias -- this works around the insanity
         * of overriding "git log" with "git show" by having
         * alias.log = show
         */
        if (done_alias || !handle_alias(argcp, argv))
            break;
        done_alias = 1;
    }

    return done_alias;
}

Ce n'est donc pas possible. ( handle_internal_command appels exit s'il trouve la commande).

Vous pouvez corriger cela dans vos sources en changeant l'ordre des lignes et en faisant en sorte que handle_alias appel exit s'il trouve l'alias.

17 votes

Git config devrait probablement émettre une sorte d'avertissement si l'on essaie de créer un alias qui est identique à une commande interne/externe... Ironiquement, je n'arrive pas à trouver où signaler des problèmes pour git-scm lui-même. Les résultats de Google et de Stack Overflow semblent tous être brouillés par des outils de gestion des problèmes AVEC Git.

0 votes

Cela nécessite de modifier le code source de git. Je peux remplacer libexec/git-core/git-commit avec ma version personnalisée.

0 votes

@DanielHershcovich D'accord ; j'aimerais vraiment m'engager dans git (jeu de mots :p), mais leur processus de développement semble très dispersé.

40voto

stefan Points 11

J'ai choisi de résoudre ce problème à l'aide d'une fonction bash. Si j'appelle git clone il redirigera l'appel vers git cl qui est mon alias avec quelques options supplémentaires.

function git {
  if [[ "$1" == "clone" && "$@" != *"--help"* ]]; then
    shift 1
    command git cl "$@"
  else
    command git "$@"
  fi
}

28voto

David Mertens Points 478

Comme indiqué précédemment, il n'est pas possible d'utiliser un alias git pour remplacer une commande git. Cependant, il est possible de remplacer une commande git en utilisant un alias shell. Pour tout shell POSIXy (c'est-à-dire non MS cmd ), écrire un simple exécutable script qui exécute le comportement modifié souhaité et définir un alias shell. Dans mon .bashrc (Linux) et .bash_profile (Mac) J'ai

export PATH="~/bin:$PATH"
...
alias git='my-git'

Dans mon ~/bin J'ai un script Perl exécutable script appelé my-git qui vérifie si le premier argument (c'est-à-dire la commande git) est clone . Il se présente essentiellement comme suit :

#!/usr/bin/env perl
use strict;
use warnings;
my $path_to_git = '/usr/local/bin/git';
exit(system($path_to_git, @ARGV))
    if @ARGV < 2 or $ARGV[0] ne 'clone';
# Override git-clone here...

Le mien est un peu plus configurable, mais vous voyez l'idée.

22voto

Ciro Santilli Points 3341

Ce n'est pas seulement impossible, c'est aussi impossible.

En 2009 http://git.661346.n2.nabble.com/allowing-aliases-to-override-builtins-to-support-default-options-td2438491.html

Hamano répond :

Actuellement, git ne permet pas aux alias de remplacer les composants intégrés. I Je comprends le raisonnement derrière cela, mais je me demande si ce n'est pas trop conservateur. conservateur.

Ce n'est pas le cas.

La plupart des shells permettent de remplacer des commandes par des alias, et je ne suis pas sûr que pourquoi git doit être plus conservateur que l'interpréteur de commandes.

Parce que les shells sains ne développent pas les alias lorsqu'ils sont utilisés dans un script, et que donne un moyen pratique d'annuler l'alias même à partir de la ligne de commande.

$ alias ls='ls -aF'
$ echo ls >script
$ chmod +x script

et comparer :

$ ./script
$ ls
$ /bin/ls

2voto

Dabe Murphy Points 81

Pour info, j'ai résolu le problème (ok, "l'a contourné" ...) en écrivant ce qui suit ~/bin/git qui vérifie, par exemple, la présence de ~/bin/git-clone et appelle que au lieu de la version intégrée.

[NOTE : Je m'excuse pour tous les bash-ismes "intelligents", mais après avoir passé les deux fonctions d'aide - une pour développer les liens symboliques et une pour rechercher dans votre $PATH l'exécutable à envelopper - le script lui-même n'est que Three Lines of Code™ (trois lignes de code)... Je crois que je ne suis pas désolé après tout, hehe !].

#!/usr/bin/env bash

###########################
###  UTILITY FUNCTIONS  ###  ...from my .bashrc
###########################
#
# deref "/path/with/links/to/symlink"
#   - Returns physical path for specified target
#
# __SUPER__
#   - Returns next "$0" in $PATH (that isn't me, or a symlink to me...)

deref() {
  ( # Wrap 'cd's in a sub-shell
    local target="$1"
    local counter=0

    # If the argument itself is a link [to a link, to a link...]
    # NOTE: readlink(1) is not defined by POSIX, but has been shown to
    #  work on at least MacOS X, CentOS, Ubuntu, openSUSE, and OpenBSD
    while [[ -L "$target" ]]; do
        [[ $((++counter)) -ge 30 ]] && return 1
        cd "${target%/*}"; target="$(readlink "$target")"
    done

    # Expand parent directory hierarchy
    cd "${target%/*}" 2>/dev/null \
      && echo "$(pwd -P)/${target##*/}" \
      || echo "$([[ $target != /* ]] && echo "$(pwd -P)/")$target"
  )
}

__SUPER__() {
  local cmd="${1:-${0##*/}}"
  local me="$(deref "$0")"

  # NOTE: We only consider symlinks...  We could check for hardlinks by
  #       comparing device+inode, but stat(1) has portability problems

  local IFS=":"
  for d in $PATH; do
    [[ -x "$d/$cmd" ]] && [[ "$(deref "$d/$cmd")" != "$me" ]] \
      && { echo "$d/$cmd"; return; }
  done

  # else...
  return 1
}

########################################################################

# (1) First, figure out which '$0' we *WOULD* have run...

GIT="$(__SUPER__)" || { echo "${0##*/}: command not found" >&2; exit 1; }

# (2) If we have a "~/bin/git-${command}" wrapper, then
#     prepend '.../libexec/git-core' to $PATH and run it

[[ -f "${HOME}/bin/git-$1" ]] &&
  PATH="$PATH:$( "$GIT" --exec-path )" \
    exec "${HOME}/bin/git-$1" "${@:2}"

# (3) Else fall back to the regular 'git'

exec "$GIT" "$@"

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