Introduction
Utilisateur de Git depuis maintenant plus de deux ans, il me paraît logique de parler de cet outil, et des points forts ou défauts que je lui trouve.
À noter que la plupart des arguments ne sont pas spécifiques à cet outil, et que j’aurais probablement pu utiliser un autre outil du même style, comme Mercurial ou Bazaar, pour les mêmes résultats.
Qu’est-ce que Git ?
Git est un outil de contrôle de source, permettant de suivre l’historique des modifications sur un projet [1]. C’est un outil distribué, il n’y a pas de dépôt central de sources, contrairement à des logiciels comme Subversion, CVS ou Team Foundation Server [2].
Git a été conçu par Linus Torvalds, créateur du noyau Linux, pour gérer les sources du noyau [3], et est un logiciel libre [4].
Il propose les fonctions standard d’un contrôle de source, à savoir suivi des modifications, étiquettes sur les modifications, branches, etc.
Outil distribué
Git est un outil distribué, ce qui signifie que chaque développeur a son propre dépôt en local [5]. Pour transmettre leurs modifications à d’autres, les développeurs leur demandent de pull [6] depuis leur dépôt, push vers un dépôt distant ou envoient les modifications par mail. Avantage, il est possible de travailler sans connexion Internet, notamment en déplacement.
Il n’y a donc pas à proprement parler de « dépôt maître » contenant toutes les modifications, chacun a potentiellement des modifications spécifiques en local. Il est cependant possible, voire très utile, d’avoir un dépôt sur lequel tous les développeurs poussent leurs modifications pour des besoins de synchronisation des sources et afin de tester l’intégration complète du code.
Les dépôts vers ou depuis lesquels les modifications sont transmissibles ou récupérables peuvent être en local [7], ou sur des serveurs distants via des protocoles comme FTP, SFTP, SSH.
Conséquence de l’absence de centralisation, il n’y a pas de numéro de révision [8] comme sur SVN ou TFS. Chaque révision a un identifiant unique [9], et il y a également des façons de spécifier rapidement les révisions précédant la dernière révision de la branche courante.
L’inconvénient de cette stratégie de stockage est que la taille du dépôt peut être importante, surtout s’il y a de nombreux fichiers binaires régulièrement modifiés.
Rapidité des fonctions habituelles
Parce que l’intégralité du dépôt est disponible sur le propre poste du développeur, de nombreuses fonctions sont très rapides : validation de modification, affichage d’historique, fusion de branches, etc. Des logiciels ayant un dépôt centralisé doivent interroger ce dépôt pour par exemple récupérer l’historique, ce qui entraîne des temps de latence [10].
La validation de modifications, en particulier, est très rapide. Du coup moins d’attente, et une plus grande tendance à faire des validations petites modifications par petites modifications plutôt que par gros blocs. Bien sûr cette politique de validation incrémentale est possible sur n’importe quel contrôle de source. Mais si chaque validation prend une ou deux secondes, le développeur attend au final un certain temps. Cette attente dans mon cas peut « casser » mon rythme de travail, alors qu’une validation quasi instantanée me permet de continuer rapidement.
Transmission automatique des sources
Même si chacun a son propre dépôt en local, il est possible, grâce aux « hooks », de configurer Git pour qu’à chaque validation de modification celle-ci soit transmise sur un serveur distant. Cela permet de dupliquer les sources sur différents disques durs, ou différentes machines. Cela permet également une mise à jour instantanée sur des dépôts distants.
Modifications en attente
Git permet simplement de mettre en attente des modifications pour une utilisation future, via sa commande stash. Ceci permet d’expérimenter une modification mineure, la stocker dans un coin pour retravailler dessus plus tard, sans aller jusqu’à utiliser une branche.
Puissance des branches
La gestion des branches par Git est simple et puissante, et est pour moi une raison majeure d’utiliser cet outil plutôt que SVN que j’utilisais précédemment.
Par défaut la branche créée par Git est nommée master et est considérée la principale.
La création d’une branche, à partir d’une autre branche, est une opération très simple et quasiment instantanée [11]. Chaque branche est identifiée par un nom et peut être renommée.
Il est simple d’obtenir les modifications entre différentes branches, et de fusionner, en totalité ou partiellement, ces modifications entre branches. Cerise sur le gâteau, la fusion peut soit préserver l’historique, soit n’ajouter à la branche destination qu’une unique révision, ce qui permet de ne garder que le résultat final sans les étapes intermédiaires.
Git gère la fusion de branche de façon « intelligente », gardant trace de ce qui a été fusionné ou non. Il interdira ainsi la suppression accidentelle d’une branche non fusionnée dans master. La fusion croisée, pour récupérer des modifications en parallèle, est également bien gérée.
Conséquence, il devient pour moi quasiment un réflexe de créer une branche avant de commencer des modifications importantes, voire mineures. Les modifications finies, la fusion de la branche sur la branche d’origine est simple, et utiliser une branche permet de retravailler sur la branche d’origine sans inclure des modifications en cours, ou de totalement jeter ces modifications, si elles s’avèrent une impasse, sans impact.
Autre usage, créer une branche pour chaque fonction majeure permet de ne fusionner que certaines sur la branche principale, après validation, et d’en laisser d’autres en attente, ou de les supprimer plus tard.
Bien évidemment l’échange de branches entre développeurs est possible. Les branches étant locales par défaut, les dépôts des autres développeurs ne sont pas impactés par ces modifications partielles.
Exemple d’utilisation : à partir de master, une branche fonction est créée, sur laquelle une nouvelle fonction est développée. Durant le développent un bug est signalé. Une branche correction est créée depuis master, sur laquelle le bug sera corrigé avec plusieurs révisions. Puis correction est fusionnée vers master et éventuellement supprimée, enfin master est fusionnée vers correction afin de confirmer que les modifications n’impactent pas la nouvelle fonction. Une fois la nouvelle fonction terminée et validée, correction est fusionnée vers master.
Un outil puissant, à manier avec précaution
Git demandera confirmation avant de faire certaines choses « critiques », comme supprimer une branche non fusionnée sur la branche principale et perdre des modifications. Cependant des commandes comme pull agiront sans confirmation, et sans possibilité d’annuler l’opération. Il est donc nécessaire d’utiliser cette fonction avec attention [12].
Conclusion
Git est pour moi un très bon outil, car il correspond à ma façon de travailler : de façon décentralisée, avec potentiellement plusieurs modifications en parallèle, en attente de validation ou simplement expérimentales, rapidité des opérations usuelles.
Je n’ai cependant pas eu l’occasion de travailler sur des projets impliquant de nombreuses personnes, aussi je ne peux pas juger si cet outil serait adapté ou non. Le fait qu’il soit utilisé pour le développement du noyau Linux, avec plusieurs centaines ou milliers de contributeurs, me laisse à penser qu’il fonctionnerait parfaitement.
Bien sûr il n’est pas forcément adapté à tous les développeurs, chaque personne ayant sa façon de travailler et de structurer ses développements.