J’utilise GIT depuis quelques mois, et je trouve ça vraiment génial. Si vous ne connaissez pas, ou peu, vous ne pouvez pas ne pas lire le livre Pro Git (sous licence cc-by-nc-sa). Les explications très claires permettent en quelques heures de maîtriser toutes les fonctions de base, et d’être à l’aise avec la gestion des branches (et bien plus encore).
Branches visibles
Le but de ce billet est de répondre à un problème particulier : par manque d’attention, il m’est arrivé plusieurs fois de commiter des changements sur une mauvaise branche (j’étais persuadé d’être sur une branche, en fait j’étais sur une autre). Ce n’est pas très grave (on peut s’en sortir), mais c’est pénible.
Je souhaiterais donc avoir le nom de la branche dans le prompt bash.
Des solutions existent déjà : le paquet git embarque même un script qui répond au besoin. Certains utilisent aussi des scripts personnalisés. Mais aucun de ceux que j’ai trouvés ne me convenait. J’ai donc écrit mon propre script.
Mes prompts
Version simple
J’ai commencé par une version simple, qui ajoute en couleur @nomdelabranche à la fin du prompt. Un exemple vaut mieux qu’un long discours :
rom@rom-laptop:~/dev$ cd myproject/ rom@rom-laptop:~/dev/myproject@master$ git checkout testing Switched to branch 'testing' rom@rom-laptop:~/dev/myproject@testing$ cd img rom@rom-laptop:~/dev/myproject/img@testing$
Dans une arborescence ayant plusieurs projets GIT imbriqués (dans le cas de l’utilisation de sous-modules), la branche des projets parents n’est pas affichée :
rom@rom-laptop:~/dev$ cd mybigproject/ rom@rom-laptop:~/dev/mybigproject@master$ cd submodule/ rom@rom-laptop:~/dev/mybigproject/submodule@master$ git checkout exp Switched to branch 'exp' rom@rom-laptop:~/dev/mybigproject/submodule@exp$ cd .. rom@rom-laptop:~/dev/mybigproject@master$
Version améliorée
Dans cette version simple, le nom de la branche est toujours affiché à la fin. Cela ne me convient pas, je le voudrais toujours à la racine du projet en question. C’est ce que permet la version améliorée.
Voici le résultat avec les mêmes commandes :
rom@rom-laptop:~/dev$ cd myproject/ rom@rom-laptop:~/dev/myproject@master$ git checkout testing Switched to branch 'testing' rom@rom-laptop:~/dev/myproject@testing$ cd img rom@rom-laptop:~/dev/myproject@testing/img$
Et avec des sous-modules, la branche des projets parents est affichée :
rom@rom-laptop:~/dev$ cd mybigproject/ rom@rom-laptop:~/dev/mybigproject@master$ cd submodule/ rom@rom-laptop:~/dev/mybigproject@master/submodule@master$ git checkout exp Switched to branch 'exp' rom@rom-laptop:~/dev/mybigproject@master/submodule@exp$ cd .. rom@rom-laptop:~/dev/mybigproject@master$
Script
Le script, sous licence WTFPL, est disponible sur un dépôt git :
git clone http://git.rom1v.com/gitbashprompt.git
(ou sur github)
Une fois cloné, éditez le fichier ~/.bashrc pour remplacer l’initialisation de la variable PS1 :
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
par :
. your_cloned_repo/gitbashprompt
Pour tester, ouvrir un nouveau terminal.
Conclusion
Tout d’abord, je suis content d’avoir exactement le comportement que je souhaitais pour mon GIT.
Ensuite, j’ai découvert le fonctionnement du prompt, avec notamment les subtilités d’échappement de caractères de la variable PS1 et la prise en compte des caractères de contrôle « \[ » et « \] ».
Enfin, je me suis enfin décidé à étudier la gestion des couleurs de Bash (qui, à première vue, est assez repoussante, il faut bien l’avouer). Mes scripts seront donc plus jolis à l’avenir




Merci pour l’astuce,
Très utile
C’est pas ce que propose nativement ZSH ? Ou alors c’est via Oh My ZSH ?
@tominardi :
Je viens de tester, nativement, non.
Je ne connaissais pas oh-my-zsh, je testerai quand j’aurai un moment. Si tu l’utilises, tu peux indiquer ce qu’il fait exactement pour GIT ?
je me demande, si ça ressembla pas à çà…
https://yeevgen.wordpress.com/2011/05/23/mercurial-zsh-prompt/
Merci pour ce petit script très pratique.
Cependant j’ai eu un problème chez moi, il a fallut que j’enlève des guillemets pour qu’il marche:
Je viens de mettre à jour le script (v0.11), car la première version n’affichait plus du tout le chemin lorsqu’on était dans un répertoire hors du home (quand le chemin affiché commençait par
/).Améliorer son prompt pour supporter git est vraiment quelque chose d’obligatoire une fois que l’on utilise fréquement git.
Personnellement, j’utilise zsh avec un script custom pour afficher les informations de Git, pour l’instant je n’affiche que la branche courant et l’état du répo (modified ou up-to-date).
Et pour info, oh-my-zsh utilise un principe de plugin pour afficher un prompt « git » complet, il est même possible d’afficher dans le prompt si on est en avance ou en retard sur l’origin.
pums974 :
Ah, bizarre, je ne comprends pas pourquoi.
Cependant, pour moi il faut des guillemets (si on ancien
IFScontenait par exemple un~, il ne faut pas que bash l’interprète).Peux-tu nous montrer ton
IFS:?
C’est vrai que se passer de ce genre d’infos une fois qu’on y a goûté, c’est difficile.
C’est un minimum d’afficher la branche mais je trouve qu’afficher l’état du dépôt (nouveau fichier non ajouté au dépôt, fichier modifié) est indispensable également.
Pour ma part, j’utilise le module vcs_info de zsh. C’est vraiment super efficace et cela se configure selon ses envies. De plus, pratiquement tous les VCS sont supportés (git, hg, svn, etc.).
J’en avais fait un article en janvier dernier, si cela intéresse quelqu’un…
J’aime bien ton « par manque d’inattention »
@bartounet :
Merci, corrigé.
En plus, ce matin, je me suis dit qu’il fallait que je vérifie, car il me semblait bien avoir écrit « par manque d’inattention ». Mais j’ai finalement oublié de vérifier, sans doute par manque de déconcentration
le packet git de mageia (rpm chez moi: git-core-1.7.4.4-2.mga1), a modifié la variable PS1 par défaut et installé un fichier pour bash_completion (
/etc/bash_completion.d/git) qui fait déjà cela (et même bcp plus, cf. completion).voila mon PS1 :
(j’ai rajouté
\$?…)Merci beaucoup !
Une suggestion : pourquoi ne pas mettre ton script dans github ?
@Asenar :
C’est vrai que j’aurais pu mettre le script sur un dépôt git. D’ailleurs, je le fais :
Pour github, j’essaie d’éviter (autant que faire se peut) les services centralisés, d’autant qu’il n’est pas libre…
Après, techniquement, je ne dis pas, c’est sympa les pull requests et tout ça… Une solution pragmatique serait de le mettre sur github en plus d’un dépôt sur lequel on a la main.
Mais pour un simple script comme celui-là, je vais me contenter de mon dépôt http
J’utilise ça :
https://github.com/olivierverdier/zsh-git-prompt
ça permet d’avoir le `git status` dans le prompt également
Bonsoir,
Il est vrai que le livre Pro Git est assez formidable. Perso, j’utilise Git depuis un moment maintenant pour mes projets Java et je trouve cet outil super puissant, facile à utiliser et rapide. Un utile vraiment utile !
Je pense donc que c’est une bonne chance d’en parler à travers un blog, cela promeut l’outil
.
Bonne soirée,
Je viens de publier une version 0.12, qui corrige un petit bug dans certains cas lorsqu’on utilise les sous-modules.
En effet, le répertoire
.gitd’un sous-module peut se trouver ailleurs qu’à la racine du projet, et être référencé par un fichier.gitcontenant par exemple :Avec la version 0.11, la branche ne s’affichait pas dans ce cas, c’est maintenant corrigé.
Bonjour,
Encore merci pour ton script, je l’utilise quotidiennement.
Petite remarque, sous bash, il y a un (bug ? comportement bizarre ?) qui fait qu’on peut mettre deux / en début de chemin et dans ce cas, ton script ne fonctionne pas (aucun chemin n’est affiché).
Je sais c’est un peu du pinaillage mais j’ai eu le cas ce matin et je ne comprenais pas pourquoi je ne retrouvait plus mon repo ^^
@huit_six :
Je ne savais pas qu’on pouvait mettre
//en début de chemin. Que cela signifie-t-il ?Tu peux préciser le chemin que tu mets stp pour reproduire le problème ?
J’ai essayé avec un projet git dans
//tmp, je n’ai pas eu de problème…L’implémentation est peu efficace : tout le code shell est dans la variable PS1, donc le parsing des 40 lignes de code shell (la grosse boucle while) et la vérification de la syntaxe sont fait à chaque affichage du prompt. Une meilleure solution serait de faire comme fait le plugin Git de bash (voir
__git_ps1): mettre le code dans une fonction et ne mettre dans PS1 que l’appel à la fonction.De plus les variables
coletnocolpourraient être développées et supprimées de l’environnement.@Olivier Mengué (dolmen) :
Bonnes remarques.
Quand j’aurai un moment, j’en ferai une fonction à part.
@Olivier Mengué (dolmen) :
J’ai donc mis le contenu de la fonction dans une fonction à part, et je l’ai appelée dans
PS1.J’ai créé une nouvelle branche temporaire nommée func pour cette modif :
Mais je n’arrive pas à faire fonctionner les couleurs comme avant.
En effet, si j’utilise le script que je t’envoie tel quel, ça affiche les
\[:~/MonProjet\[\]@master\[\]$Si je retire ces
\[\]"en trop", ça s'affiche correctement, mais le terminal, lui, se trouve buggé : il retourne à la ligne avant la fin de la ligne (et écrit par-dessus le texte déjà présent) car il "croit" que les codes couleurs (\e[34m) comptent pour 6 caractères, alors qu'en réalité aucun de ces caractères n'est affiché. C'est la raison pour laquelle j'avais encadré le code couleur de\[et\]dans ma première version, mais ça ne semble pas fonctionner s'ils se trouvent dans une fonction à part.As-tu une idée ?
J’ai trouvé !
\[et\]ne sont interprétés que parPS1, dans une fonction il faut utiliser\001et\002.Un bout du commit qui résout le problème (
1d062d9) :--- gitbashprompt +++ gitbashprompt @@ -9,8 +9,8 @@ __git_bash_prompt() { # Colors - local nocol='\[\e[0m\]' - local col='\[\e[34m\]' # blue + local nocol='\001\e[0m\002' + local col='\001\e[34m\002' # blue SFI="$IFS" IFS=/Cette nouvelle version du script (0.2) a maintenant été mergée sur la branche
masteret supprimé la branche temporairefunc.Connaissez-vous LiquidPrompt ?
https://github.com/nojhan/liquidprompt
Il affiche:
- Le niveau de batterie à partir d’un seuil
- Le proxy
- La charge à partir d’un seuil
- Dans un dossier git, la branche, le nombre de commit par rapport au remote etc
etc