Gérer vos sources avec Git et Mercurial

#git#outil#usine logicielle

Lors du développement de logiciels informatiques ou autre projet manipulant un système de fichiers, la gestion en configuration des sources est devenue une brique essentielle des nouvelles architectures. Git et Mercurial, créés respectivement par Linus Torvalds et Matt Mackall, sont des gestionnaires de version répondant parfaitement à ce besoin. En effet, lors du démarrage d’un projet, la mise en place d’un gestionnaire de version est une étape incontournable et ceci pour plusieurs raisons : archiver les étapes du développement, consulter les différences entre deux versions, permettre aux développeurs de travailler de manière collaborative, et bien d’autres choses encore. Les premières versions ont été publiées en 2005 mais étaient au départ peu connues du grand public. Initialement développé pour le noyau Linux, Git a su évoluer au fil du temps, tout comme Mercurial, jusqu’à devenir un outil très performant et de plus en plus populaire dans les nouvelles architectures de projets informatiques. D’ailleurs, contrairement à CVS ou SVN, Git et Mercurial se basent sur une architecture décentralisée, c’est-à-dire qu’il n’est pas obligatoire de disposer d’un serveur maître pour les utiliser. Chaque dépôt (répertoire source d’un utilisateur) peut se synchroniser l’un avec l’autre. Bien sûr, pour des raisons évidentes, la mise en place d’un dépôt maître reste appréciable, puisqu’il permet au collaborateur de récupérer le projet depuis n’importe où. Cet article est une introduction pratique qui permet de se familiariser et débuter avec Git et Mercurial.

Différences entre Git et Mercurial

Lors de la mise en place ou de l’évolution de l’architecture d’un projet, une des premières questions qui ressort est : quel gestionnaire de sources retenir pour mon système ? Beaucoup d’articles traitent de la comparaison entre Git et Mercurial afin d’analyser leurs différences et aider à faire un choix entre les deux. Dans la plupart des cas, c’est plus une question de ressenti qui va dicter le choix. En effet, il y a de nombreux points communs entre Git et Mercurial. Ce sont tous les deux des contrôleurs de version décentralisés et ils se réfèrent tous deux à leur révisions avec des hash. De plus, ils représentent l’historique des modifications en graphe orienté acyclique, c’est-à-dire qu’un nouvel enregistrement peut provenir de l’association de n’importe quel autre enregistrement, et offrent également un grand nombre de fonctionnalités. Les principales différences entre les deux se situent plus au niveau technique. En effet, les deux solutions font la même chose, mais pas de la même manière. C’est notamment le cas au niveau du format et de l’architecture de stockage des données, point transparent pour l’utilisateur. Par ailleurs, Git se révèle plus souple que Mercurial car il permet la manipulation de l’historique des versions et de l’enchaînement des commits. Ceci peut représenter un avantage comme un inconvénient selon les points de vue. Dans la suite de cet article, nous traiterons en parallèle les différents aspects de ces deux outils.

Démarrage

Après avoir téléchargé et installé votre contrôleur de version sur un poste, une console d’administration, éventuellement complétée d’un outil graphique, est disponible pour exécuter les différentes commandes utiles à la gestion des fichiers d’un projet. Via cette console ou directement dans le fichier de configuration, la première étape consiste à configurer le nom et l’adresse mail que le contrôleur de version utilisera lors des commits. C’est un moyen de vous identifier lors de vos travaux sur le projet.

Pour Mercurial, il faut directement modifier le fichier de configuration ~/.hgrc, dans le répertoire UI.

Vous êtes désormais prêts à démarrer votre projet. Pour cela, vous allez avoir besoin d’un dépôt. Un dépôt est le lieu de stockage distant ou local contenant tous les fichiers de votre projet. Via la console d’administration, placez-vous dans le répertoire où vous souhaitez récupérer les sources du projet. Deux approches sont alors possibles : soit récupérer les sources d’un dépôt, soit en créer un nouveau. Si le dépôt existe déjà et que l’adresse de celui-ci est connue, il suffira de créer une copie du projet en local, en utilisant la commande suivante :

Dans le cas d’un nouveau projet, qu’il soit vide ou déjà commencé, placez-vous dans le répertoire de celui-ci via la console d’administration, et lancez la commande :

Un nouveau dossier .git ou .hg se trouve désormais à la racine de votre projet, permettant la gestion de vos sources. À partir de ce moment, votre dépôt peut devenir la source d’un autre dépôt, que ce soit sur une autre machine ou même en local.

Fonctions de base

Un des points forts de Git et Mercurial est que chaque commit se fait localement. Ceci permet entre autre deux choses : ne pas polluer un projet avec des commits multiples lors du développement d’une même fonctionnalité et travailler tout en étant hors ligne. Tout cela se fait bien sûr en conservant l’historique des évolutions, et en bénéficiant des fonctionnalités et des avantages d’un contrôleur de version.

En effet, il est possible de travailler complètement en local et de livrer les modifications sur le dépôt source uniquement lorsque la fonctionnalité est totalement développée. Les risques de bloquer la compilation du projet sont alors plus réduits, et la guerre des commits peut s’arrêter.

Voici un exemple d’enchaînement classique d’opérations sur un projet, avec leurs commandes associées. Tout d’abord la mise à jour de l’espace de travail.

Puis viennent les modifications, les ajouts et les suppressions de fichiers en local. Dans le cas de Git, toutes ces modifications sont stockées dans ce qu’on appelle l’Index.

Dans le cas de Mercurial, la notion d’Index n’existe pas, raison pour laquelle il n’est pas nécessaire d’utiliser une commande spécifique lors de la modification d’un fichier.

Il est d’ailleurs possible de visualiser à tout moment la liste des changements via la commande ci-dessous. Celle-ci liste les nouveaux fichiers, les fichiers modifiés et les fichiers supprimés.

Une fois arrivés à un palier stable du développement, vous êtes prêts pour l’enregistrement appelé « commit » ou « changeset », qui s’effectuera en local. Concernant Mercurial, cela fonctionne de la même manière, à la différence que le commit le plus récent possède l‘étiquette nommée « Tip ».

Vous pouvez bien sûr voir l’historique de toutes vos modifications avec la commande log. Comme dans la plupart des commandes, des attributs permettent de visualiser cet historique plus précisément. Par exemple, l’attribut « -p » permet de montrer les différences introduites entre chaque commit.

Il est également possible d’ajouter une étiquette, nommée tag, à un commit. Ceci permet de signaler une étape importante dans le développement, comme par exemple une livraison ou un incrément de version, et de le retrouver plus facilement. Pour ajouter une étiquette à un commit en particulier, il suffit d’ajouter des attributs spécifiques aux commandes ci-dessous.

Une fois les développements terminés, stabilisés, et le dernier commit effectué, vos changements, qui sont pour le moment dans la copie de votre dépôt local, sont enfin prêts à être envoyés à un dépôt distant. Ceci permet au reste de l’équipe de récupérer votre travail.

Gestion de branches

Les branches sont utilisées pour développer des fonctionnalités isolées des autres. Par exemple, lors d’une mise en production, il est nécessaire de conserver l’état du projet afin de pouvoir intervenir en cas de maintenance et de nouvelle livraison. Dans le cas contraire, les équipes seraient contraintes de livrer en même temps les nouvelles fonctionnalités qui sont encore en cours de développement. Les branches peuvent également être utilisées pour faire des essais de réécriture de code, d’intégration de nouvelles technologies ou tout autre genre de preuve de concept (POF).

Un dépôt Git ou Mercurial peut contenir de nombreuses branches de développement. Pour créer une nouvelle branche, que l’on nomme dans l’exemple ci-dessous « experience », il faut utiliser la commande :

Une des forces de ces deux gestionnaires de version réside dans le fait qu’il est possible de créer et de changer de branche très rapidement, contrairement à CVS ou SVN où chaque branche est stockée en local sur la machine. En effet, dans ce cas, pour créer une branche, il faut effectuer une copie complète du répertoire du projet, ce qui peut s’avérer long pour des projets à grosse volumétrie. L’avantage cependant de cette approche est qu’il est possible de travailler sur plusieurs branches en même temps, en chargeant plusieurs environnements de développement. Avec Git et Mercurial, nous travaillons uniquement sur une branche à la fois. Pour changer de branche, il suffit de lancer la commande :

Cela peut être perçu comme un inconvénient, mais le chargement et la création d’une nouvelle branche se fait en moins de cinq secondes. La commande ci-dessus peut également permettre un retour en arrière lors d’un développement que l’on ne souhaite plus conserver. Par exemple, lors d’une mauvaise manipulation, tous les fichiers modifiés sont alors écrasés.

La branche Master est la branche principale par défaut quand on crée un dépôt. Après avoir développé une nouvelle fonctionnalité sur une autre branche, il existe deux façons de réintégrer celle-ci à la branche principale (ou à une autre branche) : le « merge », qui crée un historique parallèle et le « rebase », qui crée un historique en série. Prenons l’exemple qui représente un graphe de trois commits (Figure 1).

Image 1
Figure 1

Le projet est stable et nous souhaitons développer une nouvelle fonctionnalité. Pour cela,

Nous créons la branche Experience, puis nous effectuons un commit (Figure 2). Le développement peut continuer sur les deux branches simultanément, grâce aux commandes permettant de changer de branche pratiquement instantanément (Figure 3).

Image 2
Figure 2

Image 3
Figure 3

Une fois les développements sur la branche Experience validés, la dernière étape consiste à rassembler les deux branches. Pour cela, la solution la plus souvent pratiquée est le merge. Dans ce cas, un commit avec deux parents est créé et l’historique sur chaque branche est conservé. (Figure 4)

Image 4
Figure 4

Lorsqu’un même fichier a été modifié dans chacune des branches, Git et Mercurial tentent alors d’auto-fusionner les changements. Malheureusement, cela n’est pas toujours possible et se traduit dans ce cas par des conflits. Il faut donc résoudre manuellement ces conflits en éditant les fichiers indiqués. Dans le cas où aucune modification n’a été faite sur la branche principale, le commit de merge n’est pas nécessaire et aucun conflit n’est possible.

La deuxième solution est le « rebase ». Cette commande existe nativement dans Git, mais est contenue dans une extension pour Mercurial. Dans ce cas, c’est l’historique de la branche principale qui est réécrite. Il s’agit d’une manipulation un peu risquée si vous ne maîtrisez pas complètement ce que vous souhaitez faire, car pratiquement tout est possible avec cette commande : ajouter un fichier manquant à un commit, réordonner des commits, modifier les parents d’un commit etc. Dans notre exemple, le rebase fait en sorte que les commits de la branche Experience s’adaptent à la dernière version de la branche Principale. (Figure 5)

Image 5
Figure 5

La plupart des tutoriels présentent les commandes utiles de Git et Mercurial à lancer à travers la console d’administration. Mais malgré l’avantage que cette méthode apporte au niveau de la maîtrise des opérations, il est important de pouvoir effectuer ces commandes à travers des plugins pouvant s’adapter à nos environnements de développement. Ceci est particulièrement vrai sur des commandes basiques et très souvent utilisées. Concernant Git, il en existe plusieurs selon les plateformes comme par exemple Egit, disponible pour Eclipse, et Git Extensions pour Visual Studio. Pour Mercurial, l’équivalent est également disponible grâce à l’outil VisualHG pour Visual Studio (2005, 2008 et 2010), et MercurialEclipse pour l’environnement Eclipse. Via ces plugins, vous pourrez à tout moment voir les fichiers sur lesquels vous avez travaillé et qui sont en attente de commit, changer de branche, effectuer des merges, visualiser l’historique, ainsi que la plupart des manipulations d’un contrôleur de version.

Conclusion

Git et Mercurial répondent tous deux parfaitement aux besoins des développeurs concernant la gestion des sources. Les principales différences peuvent apparaître lors d’une utilisation approfondie de ces outils, mais sont très similaires dans la plupart des cas. Mercurial possède un grand nombre d’extensions offrant des fonctionnalités supplémentaires que Git comprend généralement de manière native. Qu’il s’agisse d’un nouveau projet ou de l’évolution d’une architecture mise en place, Git et Mercurial sont les deux gestionnaires de configuration les plus populaires actuellement.

Il est possible de retrouver l’intégralité de cet article dans le numéro 158 du mois de décembre 2012 du magazine « Programmez ».