Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Git
  3. Scénario de développeur indépendant
Extrait - Git Maîtrisez la gestion de vos versions (concepts, utilisation et cas pratiques) (4e édition)
Extraits du livre
Git Maîtrisez la gestion de vos versions (concepts, utilisation et cas pratiques) (4e édition) Revenir à la page d'achat du livre

Scénario de développeur indépendant

But de ce chapitre

Ce chapitre a pour but d’expliquer comment utiliser Git à l’aide d’un scénario. En effet, pour bien apprendre à utiliser Git, il ne s’agit pas forcément de connaître toutes ses commandes sur le bout des doigts : il faut surtout connaître les concepts et savoir à quel moment il faut exécuter une action précise. Ce chapitre contiendra quelquefois des répétitions du contenu précédent du livre. Ces quelques doublons permettent à un lecteur de commencer le livre par ce chapitre sans difficulté.

Ce scénario est simplifié et concret pour expliquer le fonctionnement de Git. Ce chapitre sera donc à la fois théorique et pratique.

À la fin de ce chapitre, vous aurez appris à utiliser les principales commandes de Git avec le service en ligne Bitbucket. Vous serez autonome dans votre utilisation de Git, mais pour utiliser Git en collaboration avec d’autres personnes n’omettez pas de lire le chapitre suivant.

Le dépôt résultant de ce chapitre se trouve en ligne, hébergé sur GitHub : https://github.com/SamuelDauzon/GitMaitriserLaGestionDeVosVersions-chap-10.

Contexte du scénario

Raphaël est développeur web indépendant. Ses prestations principales sont le développement de sites web ou de sites intranet spécifiques à l’activité du client. Une fois qu’une prestation est réalisée, il assure la maintenance de son application. Il utilise depuis plusieurs années Git qui lui permet :

  • de suivre ses développements et leur évolution,

  • de collaborer avec des salariés du client,

  • de proposer à ses clients un service de qualité avec un historique complet permettant la traçabilité des modifications.

Ses clients apprécient ce service notamment parce qu’il leur permettrait de changer de prestataire plus facilement si besoin, car la compréhension du développement est ainsi plus simple.

Cela permet de montrer à ses clients qu’il a confiance en son travail et qu’il ne cherche pas à les empêcher d’aller voir la concurrence.

Aujourd’hui, Raphaël vient de conclure un contrat pour un nouveau client : M. Airadun. Il a reçu un cahier des charges qui va lui permettre de commencer à travailler dessus. Pour les besoins de notre exemple, ce contrat va être extrêmement simple puisqu’il va consister en la création d’une liste de dates d’anniversaire. En effet, le client spécifie dans le cahier des charges :

"J’en ai marre ! Je n’arrive jamais à me souvenir de l’anniversaire de ma femme et de mes enfants !"

Raphaël a donc décidé de commencer sans plus attendre le développement pour son client. Il a l’habitude d’utiliser un service en ligne lorsque le client accepte de voir son projet stocké par un tiers. Ce service en ligne s’appelle Bitbucket et sera abordé dans...

Création du dépôt

Après avoir travaillé sur la conception de son application, Raphaël est prêt pour démarrer le développement réel de celle-ci. Il va donc commencer par créer un dépôt local sur son poste. Il ouvre une interface de ligne de commande et se place dans le dossier AnniversaireListe et exécute la commande suivante :

git init 

Cette commande va créer un nouveau dépôt dans le dossier courant. Cela signifie que Raphaël va maintenant pouvoir utiliser Git, et donc les commandes Git, à l’intérieur de ce répertoire.

Techniquement, lorsqu’on exécute git init, Git crée un dossier .git dans le dossier courant. Ce dossier caché va contenir tout le contenu du dépôt. Il faut tout de même savoir que c’est uniquement Git qui doit gérer les fichiers de ce dossier. Une simple modification dans ce dossier pourrait corrompre le dépôt et l’empêcher de fonctionner correctement.

Pour l’instant, Raphaël n’a créé aucun fichier, donc il n’a rien à suivre. Il va donc pouvoir commencer son développement.

Début du développement

Pour l’instant, Raphaël n’a pas besoin de suivre des fichiers, car il n’en a pas encore. Il va donc commencer le développement en créant un fichier HTML intitulé anniversaire.html dans le dossier AnniversaireListe avec le contenu suivant :

<html>  
<head>  
    <title>Liste des anniversaires</title>  
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 
</head>  
<body>  
    <h1>Liste des anniversaires</h1>  
    <p>  
        <button onclick="javascript:anniv_liste();">Générer la liste</button> 
        <button onclick="javascript:localStorage.clear();">Supprimer</button> 
    </p>  
    <p>  
        <br />Ajouter un anniversaire  
        <br />Personne : <input type="text" id="anniv_personne" />  
        <br />Date : <input type="text" id="anniv_date" />  
        <br /><button onclick="javascript:anniv_ajout();">Ajouter</button> 
    </p>  
    <p id="anniv_liste" style="background-color:#DDD;">  
 
    </p>  
    <script type="text/javascript" src="static/js/anniversaire.js"></script> ...

Enregistrer des modifications

Une fois que les fichiers sont ajoutés à l’index, il est possible de les commiter pour les ajouter dans l’historique de Git. Un commit ne doit être effectué que sur des modifications qui représentent une tâche ou un travail précis. Il est important de rappeler que Git n’est pas un système de sauvegarde de code, mais un gestionnaire de versions. Les commits doivent représenter une modification unique qui va combler un besoin précis (correctif d’un bug, module d’une nouvelle fonctionnalité, etc.). Il ne faut pas penser qu’un commit qui ne modifie qu’une seule ligne est inutile : s’il répond à un besoin précis avec cette seule et unique ligne (comme la correction d’une syntaxe erronée), il ne faut pas le regrouper avec d’autres modifications pour former un commit plus conséquent.

Chaque commit doit contenir un message de commit qui explique l’origine des modifications. Raphaël commite à présent ses modifications avec la commande git commit :

git commit -m "Liste des anniversaires et ajout en localstorage" 

Il est conseillé de limiter la taille des messages à 49 caractères. Lorsque le commit est important et que 49 caractères ne sont pas suffisants pour écrire un message simple et explicite, il est conseillé d’utiliser l’éditeur de texte pour ajouter le message en n’utilisant pas d’argument -m.

Un nouveau git status indiquera cette fois-ci qu’aucun fichier n’a été modifié depuis le dernier commit. Cela signifie que le commit a bien été pris en compte et que les fichiers ne diffèrent plus de la dernière version du dépôt.

Après avoir effectué le premier commit...

Bitbucket

Lorsque les développeurs évoquent des services d’hébergement de dépôt, le principal site dont ils parlent est GitHub, notamment grâce aux très populaires projets libres qu’il héberge (le noyau Linux, Django, Bootstrap, etc.). Cependant, GitHub n’est pas le seul, il existe également Bitbucket qui se fait beaucoup plus discret alors qu’il possède de nombreux points communs avec GitHub.

Bitbucket est un service en ligne qui offre beaucoup de fonctionnalités :

  • Stockage de dépôts en ligne : cela permet de travailler à plusieurs sur le dépôt stocké chez Bitbucket.

  • Visualisation du dépôt : l’interface web permet de prendre connaissance des modifications effectuées dans le dépôt. L’interface est claire et est plus agréable à utiliser que la ligne de commande pour la consultation, bien qu’elle puisse être déconcertante pour les inconditionnels de la console !

  • Réseau social : avec un système de compte personnel, il est possible de participer à des projets libres. Le profil du compte affiche les participations de l’utilisateur aux projets.

  • Modification en direct : si un développeur doit faire une modification très simple dans un fichier, il peut le faire directement à partir de l’interface web. Bitbucket permet d’éditer les fichiers et de les commiter à partir d’un compte utilisateur. Bien évidemment, pour des modifications conséquentes il vaut mieux passer par le dépôt local.

Bitbucket possède en outre quelques avantages comparé à GitHub :

  • Business model favorisant les indépendants et les petites entreprises travaillant sur de nombreux projets, car GitHub et Bitbucket segmentent...

Intégrer un nouveau développement

Suite aux demandes de son client, Raphael va devoir modifier l’application. En effet, le client souhaite pouvoir ajouter une couleur de son choix pour chaque anniversaire. Le client veut payer le moins possible et demande donc la solution la moins onéreuse et la plus simple.

Raphaël modifie donc le fichier anniversaire.html de la sorte :

  • En dessous du champ date, il ajoute un champ pour définir la couleur :

<br />Couleur (ex : 0F0): <input type="text" id="couleur" /> 
  • Il modifie ensuite les fonctions anniv_ajout() et anniv_liste() du fichier static/js/anniversaire.js :

function anniv_ajout() { 
    anniv_personne = document.querySelector('#anniv_personne').value; 
    anniv_date = document.querySelector('#anniv_date').value; 
    couleur = document.querySelector('#couleur').value; 
    anniversaire = { 
        'anniv_personne': anniv_personne, 
        'anniv_date': anniv_date, 
        'couleur': couleur 
    }; 
    nb_anniv = anniv_get_nb_anniv(); 
    localStorage.setItem(nb_anniv.toString(), JSON.stringify(anniversaire)); 
    nb_anniv++; 
    localStorage.setItem('nb_anniv', JSON.stringify(nb_anniv)); 
    document.querySelector('#anniv_personne').value = ""; 
    document.querySelector('#anniv_date').value = ""; 
    document.querySelector('#couleur').value = ""; 
    anniv_liste(); ...

Annuler les modifications d’un fichier

Pour essayer d’améliorer l’exemple de couleur donnée par le libellé du champ couleur, Raphaël modifie dans le fichier anniversaire.html la ligne contenant la couleur du champ :

<br />Couleur (ex : 0F0 ou 00FF00, le nom des couleurs n'est pas 
pris en charge) : <input type="text" id="couleur" /> 

Après avoir testé cette modification, Raphaël se rend compte qu’elle n’est pas réellement très utile et qu’elle peut créer de la confusion. Il décide donc de la supprimer. Il va pour cela utiliser la commande suivante :

git checkout anniversaire.html 

Cette commande permet de demander à Git de restaurer l’état du fichier anniversaire.html tel qu’il est dans HEAD.

.gitignore : ignorer une bibliothèque

Lorsque Raphaël a fait une démonstration de la page web à son client, celui-ci lui a rétorqué : "Mais ce n’est pas pratique, comment puis-je me souvenir de tous ces codes de couleurs ? Je ne peux pas avoir quelque chose de mieux pour pas cher ?".

Raphaël va donc lui proposer un champ qui lui permettra de sélectionner une couleur à partir d’une palette. Le code couleur sera automatiquement généré à partir de la couleur choisie. En proposant cela, Raphaël sait qu’il va utiliser une bibliothèque existante qu’il a déjà rencontrée dans d’autres développements. Cela lui permet aussi de garantir un tarif très attractif, car il va réutiliser un code déjà existant.

Après que Raphaël lui a donné le tarif de la prestation, M. Airadun a directement accepté tout en marmonnant quelques réticences : "Encore une facture... Si ça avait directement été fait...".

Après avoir quitté son client, Raphaël a commencé par télécharger la bibliothèque JSColor sur le site officiel (http://jscolor.com). Il modifie ensuite le fichier anniversaire.html et ajoute la ligne suivante juste avant la balise fermante </head> :

<script type="text/javascript" 
src="static/lib/js/jscolor/jscolor.js"></script> 

Et il va modifier la ligne contenant le champ permettant de définir la couleur avec le contenu suivant :

<br />Couleur (ex : 0F0) : <input type="text" id="couleur" 
class="color" /> 

Il va ensuite créer un dossier lib (pour library) à la racine de son projet. Dans ce dossier lib, il va créer un dossier js qui va servir à stocker...

Commiter tous les fichiers ajoutés ou modifiés

Depuis le début, Raphaël ajoute les fichiers un à un dans l’index. C’est une opération répétitive, surtout lorsqu’on doit ajouter tous les fichiers ajoutés ou modifiés.

Il existe un argument à la commande git add qui permet d’ajouter tous les fichiers ajoutés/modifiés à l’index : -A.

Tout d’abord, Raphaël doit vérifier tous les fichiers ajoutés/modifiés avec la commande git status. La commande lui indique que seul le fichier anniversaire.html a été modifié. En utilisant la commande suivante, Git va ajouter les fichiers modifiés à l’index (ici uniquement anniversaire.html) :

git add -A 

Avant de commiter, Raphaël va vérifier que le fichier ne se trouve pas dans l’index avec la commande git status. Il commite alors la modification qui permet de choisir la couleur avec la bibliothèque :

git commit -m "Ajout fenetre choix couleur" 

Cette commande permet de gagner beaucoup de temps, mais elle ne doit pas empêcher de respecter deux règles :

  • Il y a des fichiers qu’il ne faut pas versionner : si Raphaël avait utilisé la commande git add -A avant de mettre en place le fichier .gitignore, il aurait versionné tous les fichiers de la bibliothèque. C’est grâce à .gitignore que le dernier commit contient uniquement les fichiers nécessaires.

  • L’atomicité des commits : les commits doivent représenter une modification indépendante des autres. Avec la commande git add -A, il ne faut pas commiter un ensemble de modifications là où plusieurs commits seraient plus adaptés.

Il est également possible de ne pas du tout passer par l’index pour commiter tous les fichiers...

Envoyer les commits au dépôt distant

En validant ses modifications, Raphaël a ajouté un commit à son dépôt local, mais pour l’instant le dépôt distant n’a aucune information sur ce dernier commit. Il va donc envoyer les modifications de sa branche courante vers le dépôt distant.

git push 

Le résultat indique que l’envoi a bien été effectué. Si un développeur est consciencieux comme Raphaël, il va également vérifier sur l’interface web de Bitbucket que son commit a été correctement pris en compte.

Afficher les différences entre deux commits

Imaginons le cas où cela fait plusieurs semaines que Raphaël n’a pas pu travailler sur son projet pour diverses raisons (attente de documents du client, vacances, etc.). Pour appréhender à nouveau le but du projet et ce qui a déjà été fait, il consulte la liste des commits (avec git log) et il décide de regarder les modifications du dernier commit. Pour cela, il doit exécuter la commande :

git diff 4702 40a42 

L’identifiant du dernier commit commence par 40a42 et l’avant-dernier commence par 4702. La commande git diff fonctionne en spécifiant deux commits.

La réponse de Git prend la forme d’une liste de lignes. Les lignes supprimées par le commit sont préfixées d’un - et sont en rouge. Les lignes ajoutées sont préfixées d’un + et sont en vert. Les autres lignes, de couleur noire, entourent chaque modification.

Il est aussi possible de voir les modifications apportées par un commit directement à partir de Bitbucket. L’avantage de passer par la ligne de commande est que vous pouvez travailler sans être dépendant du client Git.

Cloner le dépôt distant

Pendant quelques jours, Raphaël va partir en vacances. Il ne compte pas abandonner son projet pour autant et va emmener un petit ordinateur pour le continuer tranquillement. Pour avoir un dépôt propre et fonctionnel, il va cloner son dépôt sur son PC portable. Pour cela, il lui faut Git sur son PC portable. Il faut également qu’il récupère l’URL de clonage sur Bitbucket. Cette URL se trouve sur la page principale du dépôt, après avoir cliqué sur le lien Clone du menu comme le montre la capture ci-dessous :

images/10EI07.png

Ensuite, il va utiliser l’interface en ligne de commande pour se placer dans le dossier qui contiendra le projet et utiliser la commande :

git clone https://rdauzon@bitbucket.org/rdauzon/
anniversaireliste.git anniversaireVacances 

Cette commande aura pour effet de copier le dépôt dans un nouveau dossier anniversaireVacances. Cela signifie que Raphaël a accès à tous les précédents commits et aux modifications qu’ils contiennent. Cloner un dépôt ne revient pas uniquement à copier le répertoire de travail, mais à copier l’ensemble des éléments d’un dépôt.

D’ailleurs, les fichiers configurés dans .gitignore n’ont pas été copiés. En effet, ils sont totalement ignorés par Git. Il faudra donc les copier manuellement pour le moment. Ce comportement peut ne pas sembler très pratique étant donné qu’il est malgré tout nécessaire de copier manuellement une liste de fichiers pour avoir un dépôt fonctionnel. Pourtant, cette limitation est très pratique lorsque .gitignore doit ignorer des fichiers sensibles comme ceux contenant des mots de passe d’API. D’ailleurs, Git est un système...

Une branche, ça sert à quoi ?

Les branches représentent l’une des fonctionnalités les plus intéressantes de Git. Dans chaque dépôt Git, une branche est présente par défaut : la branche master. Cette branche master correspond généralement à la branche principale du projet.

Les branches correspondent à la déviation d’une autre branche (comme peut l’être une branche d’arbre vis-à-vis du tronc qui la porte). En d’autres termes, une branche est utilisée pour maintenir une version particulière du projet dans un but précis et fixé à l’avance.

Elles peuvent servir à :

  • développer une nouvelle fonctionnalité sans polluer la branche supérieure avec des modifications non validées,

  • garder une branche correspondant à une version stable définie. Par exemple, un développeur a créé une version 1.0 d’un logiciel et il ne souhaite pas y intégrer les dernières modifications.

Raphaël a envie de proposer une nouvelle fonctionnalité à son client, à savoir une proposition des couleurs utilisées. C’est-à-dire qu’en dessous du champ texte permettant de définir la couleur, Raphaël va ajouter des boutons correspondant aux couleurs déjà utilisées sur le site. Lorsque l’utilisateur cliquera sur l’un de ces boutons, le champ couleur sera rempli avec la valeur choisie. Il va tout d’abord créer sa nouvelle branche (dans son dépôt anniversaireVacances) :

git branch color_buttons  
git checkout color_buttons 

Cette commande va indiquer à Git que Raphaël souhaite travailler dans une nouvelle branche. En réalité, la branche ne sera réellement créée...

Changer de branche

Raphaël reçoit un appel urgent de son client. En effet, celui-ci n’aime pas du tout le titre de la page. Il demande donc à Raphaël de modifier le titre qui était Liste des anniversaires en Page des anniversaires.

Raphaël ne va pas effectuer cette modification sur la branche contenant les boutons des couleurs. En effet, le client refusera peut-être les boutons ou demandera une autre modification avant la mise en production. Raphaël va donc revenir sur la branche principale (la branche par défaut de Git s’appelle master) pour modifier le titre. Pour cela, il va utiliser la commande suivante :

git checkout master 

Cette commande permet de changer de branche. Un changement de branche signifie que le répertoire de travail va être mis à jour à partir des données de la branche spécifiée dans la commande. Dans ce cas, cela signifie que les modifications effectuées dans la branche color_buttons seront effacées du répertoire de travail, mais conservées par Git.

Après avoir exécuté cette commande, il est possible de vérifier la branche sur laquelle le prochain commit sera effectué avec la commande suivante :

git branch 

Cette commande affiche la sortie suivante :

  color_buttons  
* master 

Cette sortie indique qu’il y a deux branches dans le dépôt et que l’état du répertoire de travail correspond à la branche master.

Si Raphaël consulte les fichiers, il ne verra plus les modifications qu’il a effectuées pour mettre en place le système de boutons.

En regardant plus précisément les fichiers, Raphaël remarque que la bibliothèque jQuery qu’il a ajoutée dans la branche color_buttons est toujours présente. C’est normal, étant...

Fusionner deux branches

Pour présenter une démonstration du système de boutons à son client, Raphaël va se replacer dans la branche color_buttons :

git checkout color_buttons 

Il retrouve alors les modifications qu’il avait effectuées dans cette branche. Seulement, il n’y a pas la modification de titre qu’il vient de faire dans la branche master. Son client ne va pas être très ouvert à sa proposition s’il n’y a pas les modifications demandées. Raphaël va donc récupérer les modifications effectuées sur la branche master à l’aide de la commande git merge :

git merge master 

Lorsque Raphaël exécute la commande précédente, Git lui propose un message pour le commit qui va représenter les modifications de master qui seront ajoutées dans la branche color_buttons. Il garde ce message pour son commit.

Cette commande va intégrer les modifications de la branche master dans la branche colors_buttons. Implicitement, la commande git merge signifie que les modifications de la branche spécifiée seront ajoutées dans la branche sur laquelle le dépôt est positionné. Cette étape de fusion engendre parfois un conflit lorsque les mêmes parties du fichier ont été modifiées sur les deux branches. Les conflits doivent alors être résolus manuellement par le développeur.

Après avoir fait la démonstration du système de boutons à son client, celui-ci a accepté la mise à jour pour une mise en production. Il était très satisfait d’avoir un système qui lui permette de gagner autant de temps et de se souvenir de tous les anniversaires de sa famille.

Raphaël va donc inclure les modifications de la branche color_buttons vers sa branche de production...