1. Livres & 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) (5e édition)
Extraits du livre
Git Maîtrisez la gestion de vos versions (concepts, utilisation et cas pratiques) (5e édition) Revenir à la page d'achat du livre

Scénario de développeur indépendant

But de ce chapitre

Ce chapitre, à la fois théorique et pratique, a pour but d’expliquer, à l’aide d’un scénario simplifié et concret, comment utiliser Git. 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 reprend les points clés vus précédemment dans l’ouvrage, de sorte qu’il est possible de commencer le livre par ce chapitre sans difficulté.

À 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 Scénario d’équipe.

Le dépôt obtenu après avoir déroulé le scénario de développeur indépendant 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.

Raphaël utilise depuis plusieurs années Git. Git lui permet de :

  • suivre ses développements et leur évolution ;

  • collaborer avec des salariés du client ;

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

La compréhension du développement s’en trouve simplifiée, ce qu’apprécient les clients, notamment parce qu’ils sont libres de changer de prestataire plus facilement si besoin. Raphaël montre ainsi à 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 avec 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...

Création du dépôt

Après avoir travaillé sur la conception de son application, Raphaël est prêt à 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 accueillir tout le contenu du dépôt. Attention : c’est uniquement Git qui gère 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 pas créé de fichier, donc il n’en a aucun à suivre. Il va pouvoir commencer son développement.

Début du développement

Raphaël commence donc 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...

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.

Raphaël commite à présent ses modifications avec la commande git commit :

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

Chaque commit doit contenir un message de commit qui explique l’origine des modifications.

Il est conseillé de limiter la taille des messages à 49 caractères. Lorsque le commit est important et qu’il est impossible d’écrire un message simple et explicite en seulement 49 caractères...

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 service de ce type, il existe également Bitbucket édité par Atlassian, qui est 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 un avantage comparé à GitHub : son business model favorise les indépendants et les petites entreprises travaillant sur de nombreux projets. Il faut savoir que Bitbucket, à l’instar de GitHub, segmente les dépôts en deux parties : les dépôts publics, qui sont accessibles par n’importe qui, et les dépôts privés, qui sont accessibles par une équipe définie par l’administrateur du dépôt. Si Bitbucket favorise les petites équipes, c’est parce qu’il ne pose aucune limite quant au nombre de dépôts...

Intégrer un nouveau développement

Suite aux demandes de son client, Raphael va devoir modifier l’application. En effet, le client souhaite pouvoir saisir un code couleur de son choix quand il entre une date d’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()...

Annuler les modifications d’un fichier

Pour améliorer l’interface qu’il développe pour son client, Raphaël modifie dans le fichier anniversaire.html la ligne contenant le champ couleur :

<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 

Git va alors 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 couleur ? 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 déjà exploité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, son client a accepté tout en marmonnant : « Encore une facture... Si cela avait été fait directement... »

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

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

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, d’autant plus 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 en utilisant la bibliothèque :

git commit -m "Ajout fenêtre 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....

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

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 se remettre en mémoire 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 celui de l’avant-dernier commence par 4702. La commande git diff fonctionne en spécifiant deux commits par leurs références.

La réponse de Git prend la forme d’une liste de lignes. Les lignes supprimées par le commit commencent par un signe - et sont en rouge. Les lignes ajoutées commencent par un signe + 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 poursuivre 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. Il trouvera cette URL 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 aura accès à tous les précédents commits et aux modifications qu’ils contiennent. Cloner un dépôt revient à copier, non seulement le répertoire de travail, mais aussi 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....

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. Elle peut 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 en dessous du champ couleur, Raphaël va ajouter des boutons correspondant aux couleurs déjà utilisées sur le site. 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...

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...

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 contenir 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...