1. Présentation
Besoin de créer des commandes manquantes dans Git ? Besoin de raccourcis pour des actions récurrentes Git ? Vous avez sûrement déjà dû utiliser des alias Bash pour créer ce dont vous avez besoin. Mais il s’avère que Git donne aussi la possibilité de créer ses propres alias et ses commandes complexes.
Mais alors quoi choisir pour créer ces raccourcis ? Git ou Bash ?
Nous allons voir ensemble les avantages et inconvénients de ces deux approches, et nous allons découvrir comment les coupler.
Plus d’infos sur : |
2. Alias Git VS Alias Bash
2.1. Exemple d’un alias Git
$ git config --global alias.ck "checkout" # Créer l'alias `git ck`
$ git ck develop # Changement de branche avec l'alias Git
La commande $ git config --global alias.x … enregistre automatiquement l’alias dans le fichier global ~/.gitconfig . L’alias Git sera accessible depuis n’importe quel autre terminal.
|
[alias]
ck = checkout
2.2. Exemple d’un alias Bash
$ alias ck="git checkout" # Création de l'alias Bash `ck`
$ ck develop # Changement de branche avec l'alias Bash
L’alias Bash sera perdu dès la fermeture du terminal en cours. Si nous souhaitons le conserver, nous devons l’enregistrer dans le fichier ~/.bashrc ou ~/.bash_aliases .
|
2.3. Avantages et inconvénients
Git | Bash | |
---|---|---|
Usage |
|
|
Sauvegarde |
L’alias Git est enregistré automatiquement dans la configuration de Git. |
Pour être conservé, l’alias Bash doit être écrit dans le fichier |
Surcharge |
Un alias Git global peut être surchargé par l’alias Git du dépôt. |
Pas de surcharge d’alias Bash en fonction du contexte. |
Conflits |
Les alias Git et les alias Bash n’interfèrent pas entre eux. |
|
Autocomplétion |
Les alias Git bénéficient par défaut de l’autocomplétion de Git. |
Les alias Bash ne bénéficient pas par défaut de l’autocomplétion de Git. |
3. Conservez une autocomplétion contextualisée
L’alias |
Commande | Autocomplétion |
---|---|
|
Affichera les commandes et les alias disponibles dans Git. |
|
Affichera uniquement les commandes et les alias commençant par |
|
Affichera la liste des branches. |
|
Affichera les options disponibles pour |
L’alias Bash |
Commande | Autocomplétion |
---|---|
|
N’affichera rien. |
|
Affichera toutes les commandes et les alias Bash commençant par |
|
N’affichera pas la liste des branches dans Git. |
|
N’affichera rien. |
3.1. Alias Bash : comment activer l’autocomplétion Git ?
Comme les alias Bash ne bénéficient pas par défaut de l’autocomplétion de Git, vous devrez spécifier explicitement quelle autocomplétion utiliser.
Plus d’infos sur https://stackoverflow.com/a/24665529/13480534. |
Par exemple, les commandes suivantes permettent d’activer l’autocomplétion git push
pour notre alias Bash p
:
$ alias p="git push"
$ __git_complete p _git_push
3.2. Alias Git : comment choisir une autocomplétion spécifique ?
Nous verrons par la suite que certains alias Git complexes peuvent perdre une autocomplétion correcte. Dans ce cas, vous devrez spécifier l’autocomplétion dont vous aurez besoin :
Pour | Utiliser |
---|---|
|
|
|
|
|
Pas de fonction disponible |
Tapez dans votre terminal |
Par exemple, les commandes suivantes permettent d’activer l’autocomplétion git branch
pour notre alias git myalias
:
$ git config --global alias.myalias "!ici une commande complexe"
$ function _git_myalias { _git_branch; }
Plus d’infos sur https://coderwall.com/p/d2w7oa/auto-completion-within-complex-git-alias. |
4. Tuto : créer l’alias git rename
4.1. Étape #1 : créer l’alias git rename
Pour renommer nos branches locales, nous allons créer un alias git rename
, avec une autocomplétion qui affichera les branches disponibles. Notre alias sera basé sur la commande git branch
(https://git-scm.com/docs/git-branch#Documentation/git-branch.txt—m).
Création :
$ git config --global alias.rename "branch -m"
Votre nouvel alias se retrouve automatiquement dans le fichier de configuration global de Git :
[alias]
rename = branch -m
Usage :
$ git rename oldname newname # Renomme la branche `oldname` en `newname`
$ git rename newname # Renomme la branche courante en `newname`
Autocomplétion OK : |
4.2. Étape #2 : créer l’alias Bash gr
Création :
$ alias gr="git branch -m"
Usage :
$ gr oldname newname # Renomme la branche `oldname` en `newname`
$ gr newname # Renomme la branche courante en `newname`
Autocomplétion KO : |
Activation de l’autocomplétion
Exploitons l’astuce du chapitre précédent Alias Git : comment choisir une autocomplétion spécifique ? :
$ __git_complete gr _git_branch
Autocomplétion OK : |
Synthèse
$ alias gr="git branch -m"
$ __git_complete gr _git_branch
4.3. Étape #3 : créer & coupler gr
et git rename
Création :
$ git config --global alias.rename "branch -m"
$ alias gr="git rename" (1)
$ __git_complete gr _git_branch
1 | Nous rattachons l’alias gr à git rename au lieu de git branch -m . |
Deux avantages à cette approche :
-
gr
bénéficiera automatiquement de toutes les évolutions degit rename
-
Avec ce couplage, il n’est plus nécessaire de trier et de se rappeler des fonctionnalités accessibles uniquement côté Bash et celles accessibles uniquement côté Git.
4.4. Étape #4 : usage du point d’exclamation !
Durant l’exécution de la commande, nous souhaiterions afficher le message rename branch oldbranch to newbranch
. L’alias git rename
doit exécuter plusieurs actions : changer un nom de branche et afficher un message.
Pour construire des alias Git plus complexes, nous devons utiliser le point d’exclamation !
:
Ce signe indique qu’il faut exécuter une commande à part entière.
Création :
$ git config --global alias.rename '!echo "rename branch $1 to $2"; git branch -m'
[alias]
rename = "!echo \"rename branch $1 to $2\"; git branch -m"
Usage :
$ git rename oldbranch newbranch
rename branch oldbranch to newbranch
Autocomplétion KO : |
Réactivation de l’autocomplétion
Avec l’usage du point d’exclamation !
, certains alias Git complexes perdent une autocomplétion pertinente.
Pour réactiver l’autocomplétion avec les noms des branches, exploitons l’astuce vue dans le chapitre Alias Git : comment choisir une autocomplétion spécifique ?. Utilisons la méthode implicite _git_rename
,
rattachée automatiquement à l’alias git rename
:
$ function _git_rename { _git_branch; }
Autocomplétion OK : |
Et pour l’alias Bash gr
, remplaçons _git_branch
par _git_rename
:
$ __git_complete gr _git_rename
Plus d’infos sur https://coderwall.com/p/d2w7oa/auto-completion-within-complex-git-alias. |
Synthèse
$ git config --global alias.rename '!echo "rename branch $1 to $2"; git branch -m'
$ function _git_rename { _git_branch; }
$ alias gr="git rename"
$ __git_complete gr _git_rename
4.5. Étape #5 : usage de !f() { … }; f
Il serait plus pertinent d’afficher un message après la commande git branch
, et seulement si le renommage ne retourne pas d’erreur.
Par exemple, si nous renommons la branche pikachu
(qui n’existe pas) en raichu
, nous aurons l’erreur suivante :
$ git branch -m pikachu raichu
error: refname refs/heads/pikachu not found
fatal: Branch rename failed
Il faut aussi prendre en compte le fait que les arguments s’ajoutent tous à la fin de la commande rattachée à l’alias :
# Ainsi exécuter :
$ git rename <arg1> <arg2>
# Sera équivalent à exécuter :
$ echo "Rename branch <arg1> to <arg2>"; git branch -m <arg1> <arg2>
Si nous déplaçons echo
à la fin, l’alias Git donnera :
$ git config --global alias.rename '!git branch -m $1 $2; echo "Rename branch $1 to $2"'
# Ainsi exécuter
$ git rename <arg1> <arg2>
# Sera équivalent à exécuter :
$ git branch -m <arg1> <arg2>; echo "Rename branch <arg1> to <arg2>" <arg1> <arg2> (1)
Rename branch oldbranch to newbranch oldbranch newbranch (2)
1 | Les arguments <arg1> <arg2> sont nécessairement ajoutés en fin de ligne. |
2 | Le message sera mal structuré. |
Pour maîtriser ce comportement complexe, nous devons cloisonner notre commande dans une fonction !f() { … }; f
:
$ git config --global alias.rename '!f() { git branch -m $@ && echo "Rename branch $1 to $2"; }; f'
[alias]
rename = "!f() { git branch -m $@ && echo \"Rename branch $1 to $2\"; }; f"
Plusieurs astuces se cumulent ici :
-
Dans
git branch -m $@
, nous utilisons tous les arguments transmis avec$@
. -
Avec
&&
, sigit branch
retourne une erreur, on n’exécute pasecho
. -
Dans
echo "Rename branch $1 to $2"
, on réutilise les arguments$1
et$2
. -
On n’oublie pas de point-virgule
;
en fin de ligne dans le corps de la fonctionf() { …; }
. -
On ne met pas de point-virgule
;
à la fin de la commandef() { …; }; f
, pour quef
exploite les arguments transmis à l’aliasgit rename
.
Si la branche pikachu
existe, nous aurons :
$ git rename pikachu raichu
Rename branch pikachu to raichu
Si la branche pikachu
n’existe pas, nous aurons une erreur sans notre message final :
$ git rename pikachu raichu
error: refname refs/heads/pikachu not found
fatal: Branch rename failed
Si la branche raichu
existe déjà, nous aurons une erreur sans notre message final :
$ git rename pikachu raichu
fatal: A branch named 'raichu' already exists.
Plus d’infos sur https://jondavidjohn.com/git-aliases-parameters/. |
Synthèse
$ git config --global alias.rename '!f() { git branch -m $@ && echo "Rename branch $1 to $2"; }; f'
$ function _git_rename { _git_branch; }
$ alias gr="git rename"
$ __git_complete gr _git_rename
4.6. Étape #6 : affiner l’usage des paramètres
À cette étape, nous gérons les erreurs. Par contre, si nous renommons la branche courant pikachu
en raichu
, nous aurons un message de confirmation mal structuré :
$ git rename raichu
Rename branch raichu to
Dans ce cas nous avons besoin de deux choses :
-
Avoir le nom de la branche courante
-
Conditionner le comportement de l’alias
git rename
s’il n’y a pas d’argument$2
La commande git rev-parse --abbrev-ref HEAD
donne le nom de la branche courante. Utilisons la dans l’alias git rename
:
$ git config --global alias.rename '!f() { [ -z "$2" ] && o=$(git rev-parse --abbrev-ref HEAD) || o=$1 && n=${2:-$1} && git branch -m $@ && echo "Rename branch $o to $n"; }; f'
[alias]
rename = "!f() { [ -z \"$2\" ] && o=$(git rev-parse --abbrev-ref HEAD) || o=$1 && n=${2:-$1} && git branch -m $@ && echo \"Rename branch $o to $n\"; }; f"
Explications
$ git config --global alias.rename '!f() {
[ -z "$2" ] && o=$(git rev-parse --abbrev-ref HEAD) (1)
|| o=$1 (2)
&& n=${2:-$1} (3)
&& git branch -m $@ (4)
&& echo "Rename branch $o to $n"; (5)
}; f'
1 | Initialisation de la variable o (pour oldname) : si l’argument $2 est null , alors o sera la branche courante… |
2 | sinon o sera initialisé avec l’argument $1 . |
3 | Initialisation de la variable n (pour newname) : si l’argument $2 est renseigné, alors il sera utilisé. Dans le cas contraire, on utilisera l’argument $1 . |
4 | Exécution de la commande branch avec tous les paramètres. |
5 | Affichage du message. |
Nous aurons maintenant :
$ git rename raichu
Rename branch pikachu to raichu (1)
1 | Le nom de la branche courante est bien récupéré à la volée et injecté dans le message. |
Synthèse
$ git config --global alias.rename '!f() { [ -z "$2" ] && o=$(git rev-parse --abbrev-ref HEAD) || o=$1 && n=${2:-$1} && git branch -m $@ && echo "Rename branch $o to $n"; }; f'
$ function _git_rename { _git_branch; }
$ alias gr="git rename"
$ __git_complete gr _git_rename
4.7. Étape #7 : sauvegardez tous nos alias dans .bash_aliases
Dans le cadre du tutoriel, nous avons créé nos alias directement dans le terminal. Nous allons maintenant regrouper et écrire tous nos alias Git et Bash dans le même fichier ~/.bash_aliases
.
Votre fichier ~/.bashrc
va vérifier que le fichier ~/.bash_aliases
existe. Si c’est bien le cas, le fichier ~/.bash_aliases
sera importé. Vous devez retrouver la condition suivante :
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
Alias : differences entre .bash_rc , .bash_aliases et /usr/local/bin - https://askubuntu.com/questions/2528/aliases-difference-between-bash-rc-bash-aliases-and-usr-local-bin.
|
Si ~/.bash_aliases
n’existe pas
Si vous tentez de lire le fichier inexistant ~/.bash_aliases
, la commande cat
vous retournera une erreur :
$ cat ~/.bash_aliases
cat: /home/<user>/.bash_aliases: No such file or directory
Dans ce cas créons le fichier vide :
$ touch ~/.bash_aliases
Si ~/.bash_aliases
existe
Éditons le fichier :
$ vim ~/.bash_aliases
Écrivons les lignes suivantes :
# --- Alias Git ---
git config --global alias.rename '!f() { [ -z "$2" ] && o=$(git rev-parse --abbrev-ref HEAD) || o=$1 && n=${2:-$1} && git branch -m $@ && echo "Rename branch $o to $n"; }; f'
function _git_rename { _git_branch; }
# --- Alias Bash ---
# avoid error "__git_complete: command not found"
# @see https://stackoverflow.com/a/47496210/13480534
[ -f /usr/share/bash-completion/completions/git ] && . /usr/share/bash-completion/completions/git
alias gr="git rename"
__git_complete gr _git_rename
echo "Git & Bash aliases loaded!"
Dans le fichier ~/.bash_aliases , pour utiliser la fonction __git_complete , nous sommes obligés de charger auparavant le fichier /usr/share/bash-completion/completions/git . Plus d’infos sur https://stackoverflow.com/a/47496210/13480534.
|
Petits rappels pour Vim :
Touche | Action |
---|---|
i |
Insert mode |
ESC |
Command mode |
:wq |
Pour sauver et sortir |
:q! |
Pour quitter sans sauvegarder |
Quand vous avez sauvegardé votre fichier ~/.bash_aliases
, rechargez ~/.bashrc
:
$ . ~/.bashrc
Git & Bash aliases loaded!
Voilà ! Nos alias Git et Bash sont bien chargés, et le seront à chaque ouverture de terminal. |
5. Dernières astuces
5.1. Comment gérer l’erreur de frappe gti
?
Frapper gti
à la place de git
! Combien de fois vous êtes-vous agacé par une perte d’autocomplétion suite à cette petite erreur de frappe ? Remédions à ce souci avec une petite astuce vue dans https://stackoverflow.com/a/24665529 :
$ alias gti="git"
$ __git_complete gti __git_main
Maintenant, |
Vous n’avez plus qu’à ajouter ces commandes dans votre fichier ~/.bash_aliases
:
# --- Alias Git ---
git config --global alias.rename '!f() { [ -z "$2" ] && o=$(git rev-parse --abbrev-ref HEAD) || o=$1 && n=${2:-$1} && git branch -m $@ && echo "Rename branch $o to $n"; }; f'
function _git_rename { _git_branch; }
# --- Alias Bash ---
# avoid error "__git_complete: command not found"
# @see https://stackoverflow.com/a/47496210/13480534
[ -f /usr/share/bash-completion/completions/git ] && . /usr/share/bash-completion/completions/git
alias gti="git"
__git_complete gti __git_main
alias gr="git rename"
__git_complete gr _git_rename
echo "Git & Bash aliases loaded!"
5.2. Supprimer des alias du fichier ~/.gitconfig
Si vous renommez vos alias Git dans le fichier ~/.bash_aliases
, les anciens noms seront toujours conservés dans le fichier ~/.gitconfig
. Vous devrez supprimer manuellement ces anciens alias.
Méthode #1 : modifier directement le fichier
Éditer | Commande |
---|---|
La config globale |
|
La config du dépôt |
|
Méthode #2 : supprimer en ligne de commande
Supprimer | Commande |
---|---|
Un alias global |
|
Toutes les références globales dupliquées |
|
Un alias du dépôt |
|
Toutes les références du dépôt dupliquées |
|
6. Pour aller plus loin
Vous pouvez retrouver mes expérimentations d’une centaine d’alias sur le Gist Git and Bash aliases defined and documented in a single .bash_aliases
file, with Git auto-completion.
Git Xtended, mon outil maison open source, qui me facilite les commandes récurrentes avec Git, exploite tous les mécanismes vus dans cet article, et vous propose une pléiade d’alias Git et Bash bien documentés. Plus d’infos sur :
-
Le dépôt GitHub sur https://github.com/jprivet-dev/git-xtended
-
La documentation sur mon site https://www.jprivet.dev/git-xtended
Bonne lecture !