Gestion de versions

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Introduction

La gestion de versions est un élément indispensable dans le développement logiciel.

Objectifs principaux:
  • Historiser toutes les versions d’un projet (pour revenir éventuellement à un état antérieur en cas de problème)

Différentes versions d’un même projet
Figure 1. Différentes versions d’un même projet

Objectifs

Le gestionnaire de versions doit gérer :
  • plusieurs versions d’un même projet

  • plusieurs variantes d’un même projet avec maintenance en parallèle

  • plusieurs développeurs sur le même projet

Plusieurs variantes d’un même projet
Figure 2. Plusieurs variantes d’un même projet

Introduction (suite)

  • Un projet logiciel est généralement subdivisé en plusieurs composants avec des inter-dépendances

  • Le développement est un processus itératif et collaboratif :

    • itératif : plusieurs versions successives

    • collaboratif : plusieurs versions concurrentes

Gestionnaire de versions

  • C’est un logiciel (un serveur).

  • Il permet de conserver l’intégralité des versions fichiers d’un projet.

  • Il permet de connaître toute l’historique des modifications.

  • Il est généralement constitué :

    • d’un référentiel (local ou distant) : contenant toutes les versions;

    • de copies de travail : contenant les modifications d’un utilisateur qui seront ensuite incluses dans le référentiel.

Quelques exemples

  • RCS - Revision Control System, 1982

  • CVS - Control Version System, 1986

  • SVN - Subversion (SVN) 2000

  • Mercurial, 2005

  • Git, 2005

  • Breezy, 2017

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Motivation

  • Supposez que Bob est en train de préparer un rapport.

drwxr-xr-x   4 bob  staff  136 Jan 30 13:53 .
drwxr-xr-x  22 bob  staff  748 Jan 30 13:53 ..
-rw-r--r--   1 bob  staff    0 Jan 30 13:53 rapport.odt
  • Comme Bob est consciencieux, il a aussi créé une sauvegarde de son rapport.

  • Comme Bob n’est pas très fort en orthographe, il envoie ensuite son rapport pour que son amie Alice le corrige.

drwxr-xr-x   6 bob  staff  204 Jan 30 13:55 .
drwxr-xr-x  22 bob  staff  748 Jan 30 13:53 ..
-rw-r--r--   1 bob  staff    0 Jan 30 13:53 rapport.odt
-rw-r--r--   1 bob  staff    0 Jan 30 13:55 rapport_v1.odt
  • Et pour se rappeler quel texte exactement il a envoyé, il crée une copie appelée rapport_v1.

  • Pendant qu’Alice le corrige, Bob continue à travailler sur son rapport et décide de l’envoyer à Carol, pour avoir son avis.

drwxr-xr-x   6 bob  staff  204 Jan 30 13:55 .
drwxr-xr-x  22 bob  staff  748 Jan 30 13:53 ..
-rw-r--r--   1 bob  staff    0 Jan 30 13:53 rapport.odt
-rw-r--r--   1 bob  staff    0 Jan 30 13:55 rapport_v1.odt
-rw-r--r--   1 bob  staff    0 Jan 30 13:55 rapport_v2.odt
  • Il fait une copie de sont rapport avant de l’envoyer, il l’appelle rapport_v2.odt.

Bob continue à travailler sur son rapport et est prêt à envoyer son rapport, qu’il prend soin de faire une copie, appelée rapport_v3.odt.

-rw-r--r--   1 bob  staff    0 Jan 30 13:53 rapport.odt
-rw-r--r--   1 bob  staff    0 Jan 30 13:55 rapport_v1.odt
-rw-r--r--   1 bob  staff    0 Jan 30 14:05 rapport_v1_commentaires_alice.odt
-rw-r--r--   1 bob  staff    0 Jan 30 13:55 rapport_v2.odt
-rw-r--r--   1 bob  staff    0 Jan 30 14:06 rapport_v2_commentaires_carol.odt
-rw-r--r--   1 bob  staff    0 Jan 30 14:06 rapport_v3.odt

Avant d’envoyer son rapport, il reçoit les commentaires d’Alice et de Carol.

La question de Bob

  • Maintenant, Bob doit :

    • Intégrer les commentaires et les modifications de Carol faites sur une version plus ancienne.

    • Intégrer les commentaires et les modifications d’Alice, faites sur une version encore plus ancienne.

  • Et Bob se pose une question :

N’y aurait-il pas un moyen plus simple ? 🤔

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Gestion de versions

Principes de base
  • La gestion de versions se base sur les notions de diff et patch.

Diff

  • La commande diff correspond à la différence entre deux documents.



diff( ,  )  =  bandage



  • Un diff génère un fichier patch (rustine), c’est-à-dire l’ensemble des modifications que l’on doit réaliser sur un document pour en obtenir un autre

Patch

  • La commande patch applique une rustine à un document et en produit un autre



patch( , bandage )  =  

Exemple : Supposez que vous souhaitiez comparer 2 fichiers

Liste 1
Abricot
Amande
Cerise
Citron
Clémentine
Fraise
Groseille
Kiwaï
Kiwi
Mûre
Orange
Pastèque
Pêche
Pomme
Liste 2
Abricot
Amande
Arbouse
Cerise
Citron
Clémentine
Fraise
Framboise
Groseille
Kiwi
Mûre
Orange
Pêche
Pomme

Comparaison entre list1.txt et list2.txt

Fichier patch
Macaw:rapport bob$ diff list1.txt list2.txt
6a7
> Arbouse
27a29
> Framboise
33d34
< Kiwaï
50d50
< Pastèque

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Versions

versions
  • La gestion de versions organise les documents comme un graphe orienté.

  • Chaque version est en réalité un patch qui s’applique à la version précédente.

Copie de travail et référentiel

  • Chaque développeur a une copie de travail où il peut modifier ses fichiers.

  • Les développeurs ne peuvent pas modifier directement le référentiel.

Alors, comment fait Bob pour créer des versions?

workcopy

Validation

Validation
  • Action d’envoyer des modifications locales vers le référentiel.

  • Dans le jargon de la gestion de versions, on appelle cela un « commit ».

commit0

Bob crée un fichier et le valide.

git commit
commit1
  • Bob modifie son fichier et le valide à nouveau.

git commit
commit2
  • Et encore !

Commentaires

  • Chaque validation est accompagnée d’un commentaire.

  • Les commentaires permettent de comprendre les modifications.

git commit rapport.odt -m "Prise en compte des commentaires de Carol"

git commit Main.ts -m "Bug 1143 resolution"
Les commentaires sont absolument essentiels

Historique des validations

  • Il est possible de connaître l’historique des validations de chaque fichier.

  • L’historique permet de connaître rapidement l'auteur de chaque validation, la date et l'heure du changement ainsi que le commentaire associé à cette validation.

  • Il est aussi possible connaître les modifications dans les détails.

  • Supposez que Bob a validé plusieurs fois le fichier rapport.odt :

git commit  -m "Première version"
git commit  -m "Commentaires de Alice"
git commit  -m "Commentaires de Carol"
git commit  -m "Version envoyée"
L’historique du fichier:
Macaw:rapport bob$ git log rapport.odt
commit 128faba4e961a425962e59b8b0680c442528ed72 (HEAD -> master)
Author: Bob <bob@spon.ge>
Date:   Wed Jan 31 10:24:19 2018 +0100

    Version envoyée

commit 67ef417b9453f62875780a49d009d4a5215af060
Author: Bob <bob@spon.ge>
Date:   Wed Jan 31 10:23:39 2018 +0100

    Commentaires de Carol

commit a06254b8278deca2923597da8ea900d714d3870a
Author: Bob <bob@spon.ge>
Date:   Wed Jan 31 10:22:55 2018 +0100

    Commentaires de Alice

commit dc0173a93752c37e20c4b87d9023a51b1d008949
Author: Bob <bob@spon.ge>
Date:   Wed Jan 31 10:22:06 2018 +0100

    Première version

La scène

  • Tous les fichiers ne sont pas envoyés au référentiel.

  • Un fichier doit « monter sur scène » pour être pris en compte par le gestionnaire de versions.

scene
  • La scène est tout simplement un sous-ensemble des fichiers de la copie de travail.

stage
  • Dans le jargon de la gestion de versions on appelle cela un « stage ».

Retour en arrière

  • Les validations peuvent être annulées : la copie locale revient à une version précédente.

  • Le retour en arrière n’est pas vraiment une annulation :

    • il est enregistré comme une nouvelle validation.

  • On appelle cela un « revert ».

  • Bob revient à la version C1.

revert

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Collaboration

  • Essayons de compliquer un peu les choses !

math formula

Collaboration (suite)

  • Supposons que Alice et Carol souhaitent collaborer avec Bob.

  • Dans ce cas, chaque participant aura son propre référentiel, dit local.

  • La collaboration se fait à travers un référentiel partagé, dit public.

Collaboration (suite)

collaboration

Collaboration (suite)

  • Pour collaborer avec Bob, Alice et Carol doivent copier le contenu du référentiel public

  • Cette copie s’appelle un « clone ».

clone
  • Ensuite Alice et Carol peuvent modifier les fichiers localement

  • Les modifications peuvent être validées localement, créant plusieurs versions.

  • Les version d’Alice et de Carol sont indépendantes.

alice carol commit
  • Après avoir fini ses corrections, Alice souhaite les publier.

    • L’envoi des nouveautés locales au référentiel partagé s’appelle « push » (pousser).

  • Avant de publier ses changements, Alice doit d’abord rapporter les nouveautés publiques.

    • La récupération des nouveautés du référentiel partagé s’appelle « fetch » (rapporter).

  • Aucune nouveauté à rapporter :

alice fetch
alice push
  • Peu après Alice, Carol souhaite publier ses changements.

  • Tout comme Alice, elle doit d’abord rapporter les nouveautés du référentiel public.

  • Mais dans son cas, le référentiel public contient une nouvelle version

carol fetch
  • Après avoir rapporté les nouveautés publiques, Carol doit les fusionner.

  • On appelle cette fusion un « merge ».

carol merge
  • Après la fusion, Carol peut publier ses changements.

carol push
  • Enfin, Alice peut récupérer les changements faits par Carol.

  • Comme les opérations de « fetch » et « merge » se réalisent souvent ensemble, on peut les réunir dans une seule opération appelée « pull » (tirer).

alice pull

Fusion et lignes

Les gestionnaires de versions raisonnent généralement au niveau de la ligne

C’est-à-dire que :

  • Ajout de lignes autour d’une ligne inchangée → pas de conflit ✅

  • Modifications sur des lignes différentes → pas de conflit ✅

  • Modifications de la même ligne de la même manière par les deux parties → pas de conflit ✅

Conflits

Que se passe-t-il si Alice et Carol modifient exactement la même ligne de texte de façon différente ?


  • C’est un conflit 🔥, que le gestionnaire de versions ne peut pas résoudre automatiquement

  • Il apparaîtra lorsque Carol fera une fusion entre ses modifications et celles reçues du référentiel public

  • Ce sera à Carol de les résoudre, avant de pouvoir pousser les changements au référentiel public

Résolution des conflits

à voir en TP !

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Messages de validation

Tout comme les commentaires, les messages de validation sont de la documentation. Ils doivent :
  • Être clairs

  • Respecter les conventions du projet

  • Répondre aux questions suivantes :

    1. Pourquoi ce changement est-il nécessaire ?

    2. Comment aborde-t-il la question ?

    3. Quels sont les effets secondaires de ce changement ?

Pourquoi ?

Les messages bien élaborés sont indispensables pour :
  • les projets collectifs

  • contribuer à un logiciel libre

Les messages permettent de comprendre l’histoire d’un logiciel :
  • l’évolution des fonctionnalités

  • le pourquoi de certaines décisions

Les messages permettent de comprendre les raisons d’un changement et cette compréhension rend le développement et la collaboration plus efficaces.

Comparez ces deux listes de messages

$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"

e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.
2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)
147709f Tweaks to package-info.java files
22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils
7f96f57 polishing
$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"

5ba3db6 Fix failing CompositePropertySourceTests
84564a0 Rework @PropertySource early parsing logic
e142fd1 Add tests for ImportSelector meta-data
887815f Update docbook dependency and generate epub
ac8326d Polish mockito usage

Laquelle est la plus lisible ?

Les bons messages de validation sont rares !

Quelques exceptions

Quelques conseils pour écrire des messages utiles

Premier conseil

Séparez l’objet et le corps du message
Short (50 chars or less) summary of changes

More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.

Further paragraphs come after blank lines.

  - Bullet points are okay, too

  - Typically a hyphen or asterisk is used for the bullet, preceded by a
    single space, with blank lines in between, but conventions vary here

Deuxième conseil

L’object est une description succincte des changements
  • Limitez l’object à 50 colonnes

  • Commencez par une majuscule

  • Utilisez l’infinitif

Exemples de messages:
Apply consistent timeout for Cassandra integration tests

Improve documentation of 'image' parameter of Maven Plugin

Configure formatting tasks to use UTF-8 encoding

Pense-bête

  • L’object doit être le complément de la phrase suivante :

If applied, this commit will (…​)

Exemples:

If applied, this commit will Apply consistent timeout for Cassandra integration tests

If applied, this commit will Improve documentation of 'image' parameter of Maven Plugin

If applied, this commit will Configure formatting tasks to use UTF-8 encoding

Certains projets classent les changements par type

Exemples de messages:
perf(ivy): remove unused argument in hostBindings function (#34969)

fix(localize): re-enable filename in code-frame error messages (#34994)

docs: add link to publish a library in ivy guide (#34986)

Les conventions du projet Angular

Exemples de types (projet Angular):
feat

La nouvelle fonction que vous ajoutez à votre code (✨)

fix

Une correction de bug (🐛)

style

Changement relatif au style (💎)

refactor

Restructuration du code (📦)

test

Tout ce qui concerne les tests (🚨)

docs

Tout ce qui concerne la documentation (📖)

chore

Maintenance régulière du code (🎫)

perf

Tout ce qui concerne l’amélioration de la performance (🚀)

Les conventions de « Conventional Commits »

  • Convention légère pour écrire les messages de validation

  • Syntaxe:

    <type>[optional scope]: <description>
    
    [optional body]
    
    [optional footer(s)]
  • Types : fix, feat, build, chore, ci, docs, style, refactor, perf, test

Exemple :
feat!: send an email to the customer when a product is shipped

Troisième conseil

  • Le corps du message contient le quoi et le pourquoi

Le corps du message doit expliquer :
  1. Pourquoi ce changement est-il nécessaire ?

  2. Ce qui a changé (le quoi)

  3. Les effets secondaires de ce changement ?

Le message ne doit pas expliquer comment les changements ont été réalisés

Le pourquoi

Incorrect
commit 468e64d019f51d364afb30b0eed2ad09483e0b98
Author: [removed]
Date:   Mon Jun 18 16:07:37 2012 -0400

Fix missing import in compute/utils.py

Fixes bug 1014829
Correct
Add missing import of 'exception' in compute/utils.py

nova/compute/utils.py makes a reference to exception.NotFound,
however exception has not been imported.

Quatrième conseil

Utilisez des espaces pour structurer le message
commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <pieter.wuille@gmail.com>
Date:   Fri Aug 1 22:57:55 2014 +0200

   Simplify serialize.h's exception handling

   Remove the 'state' and 'exceptmask' from serialize.h's stream
   implementations, as well as related methods.

   As exceptmask always included 'failbit', and setstate was always
   called with bits = failbit, all it did was immediately raise an
   exception. Get rid of those variables, and replace the setstate
   with direct exception throwing (which also removes some dead
   code).

   As a result, good() is never reached after a failure (there are
   only 2 calls, one of which is in tests), and can just be replaced
   by !eof().

   fail(), clear(n) and exceptions() are just never called. Delete
   them.

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Forges

  • On appelle une forge un serveur Web dédié à l’hébergement de projets informatiques.

  • Généralement, une forge fournit les services suivants :

    • un ou des systèmes de gestion des versions (par exemple, Git ou Mercurial) ;

    • un gestionnaire de listes de discussion (et/ou des forums) ;

    • un outil de suivi des bugs (par exemple Jira, Redmine, Bugzilla) ;

    • gestionnaire de documentation (wiki) ;

    • gestionnaire des tâches.

Exemples de forge

Plan

  • Introduction

  • Motivation

  • Principes de base

  • Versions

  • Collaboration

  • Messages de validation

  • Forges

  • Conclusion

Résumé des commandes Git

CommandeDescription

git clone <url>

copie un projet d’un référentiel public

git add <file>

ajoute un fichier à la scène

git commit

valide les changements des fichiers « montés sur scène »

git status

montre l’état des fichiers de la copie locale

Résumé des commandes Git (suite)

CommandeDescription

git fetch

rapporte les nouveautés publiques

git merge

fusionne les changements rapportés

git pull

rapporte les nouveautés et fusionne si besoin

git push

publie les nouveautés du référentiel local

Autres commandes Git utiles

CommandeDescription

git rm <file>

supprime un fichier

git log

affiche l’historique des modifications (commits)

Une commande bien pratique

Pour ajouter à la scène tous les fichiers modifiés, et valider ces changements (avec un commentaire), on peut utiliser directement

git commit -a -m "commentaire"

L’option -a signifie all et prend en compte tous les fichiers déjà versionnés

Conclusion

  • Les premiers gestionnaires de versions ont été créés dans les années 1980 (GNU RCS)

  • Ils ont beaucoup évolué depuis, surtout après la montée en popularité des logiciels libres.

  • Grâce à l’historique des modifications, ils fournissent un vrai « filet de sécurité » aux développeurs

  • Actuellement, il est impensable de réaliser un projet informatique (même modeste) sans un gestionnaire de versions.

Derniers conseils

  1. Utilisez toujours un gestionnaire de versions, même pour les petits projets.

  2. Validez souvent

  3. Validez très souvent

  4. Récupérez souvent les changements publics

    • Sinon : conflits ! 🔥

  5. Utilisez des outils dédiés

Demo !