Vous êtes sur la page 1sur 50

Cours : Gestion de source et Versioning

Master 1 : Ingénierie des SI (ISI-SSI)


Département ESMT TIC
Jan-Fev 2021

Auteur : Jean Luc SEMEDO


Introduction
Système de Gestion de Pourquoi un système de gestion
Version de version ?

Système logiciel permettant de maintenir et • Revenir aisément à une version précédente.


gérer toutes les versions d'un ensemble de
• Suivre l'évolution du projet au cours du temps.
fichiers.
• Permettre le travail en parallèle sur des parties
disjointes du projet et gérer les modifications
concurrentes.
• Faciliter la détection et la correction d'erreurs.
Ouvrage de référence
http://git-scm.com/book
Différents types de versioning
La méthode courante pour la gestion de version est généralement de recopier les
fichiers dans un autre répertoire (peut-être avec un nom incluant la date dans le
meilleur des cas).

Cette méthode est la plus courante parce que c’est la plus simple, mais c’est
aussi la moins fiable.
Il est facile d’oublier le répertoire dans lequel vous êtes et d’écrire
accidentellement dans le mauvais fichier ou
d’écraser des fichiers que vous vouliez conserver.

Pour traiter ce problème, les programmeurs ont développé il y a longtemps des


VCS locaux qui utilisaient une base de
données simple pour conserver les modifications d’un fichier.
Différents types de versioning

LOCAL

SYSTEME DE
GESTION DE VERSION
LOCAL

Avantages :
Gestion et utilisation très
simples.

Inconvénients :
Très sensible aux pannes.
Ne permet pas la
collaboration.
Différents types de versioning

Le problème majeur que les gens rencontrent est qu’ils ont besoin de collaborer
avec des développeurs sur d’autres ordinateurs.

Pour traiter ce problème, les systèmes de gestion de version centralisés (CVCS


en anglais pour Centralized Version Control Systems) furent développés.

Ces systèmes tels que CVS, Subversion, et Perforce, mettent en place un serveur
central qui contient tous les fichiers sous gestion de version, et des clients qui
peuvent extraire les fichiers de ce dépôt central.

Pendant de nombreuses années, cela a été le standard pour la gestion de


version.
Différents types de versioning

CENTRALISE

SYSTEME DE
GESTION DE VERSION
CENTRALISE

Avantages :
Structurellement simple.
Gestion et utilisation simples.

Inconvénients :
Très sensible aux pannes.
Inadapté aux grands projets
c’est-à-dire avec une grande
structure hierarchique.
Différents types de versioning

Ce schéma offre de nombreux avantages par rapport à la gestion de version locale. Par exemple,
chacun sait jusqu’à un certain point ce que tous les autres sont en train de faire sur le projet. Les
administrateurs ont un contrôle fin des permissions et il est beaucoup plus facile d’administrer un
CVCS que de gérer des bases de données locales.

Cependant ce système a aussi de nombreux défauts. Le plus visible est le point unique de panne
que le serveur centralisé représente. Si ce serveur est en panne pendant une heure, alors durant
cette heure, aucun client ne peut collaborer ou enregistrer les modifications issues de son travail.
Si le disque dur du serveur central se corrompt, et s’il n’y a pas eu de sauvegarde, vous perdez
absolument tout de l’historique d’un projet en dehors des sauvegardes locales que les gens
auraient pu réaliser sur leurs machines locales.

Les systèmes de gestion de version locaux souffrent du même problème — dès qu’on a tout
l’historique d’un projet sauvegardé à un endroit unique, on prend le risque de tout perdre.
Différents types de versioning

DISTRIBUE

SYSTEME DE
GESTION DE VERSION
DISTRIBUE

Avantages :
Moins sensibles aux pannes.
Adapté aux grands projet.

Inconvénients :
Gestion et utilisation plus
complexes.
Peut structurellement être
complexe.
Différents types de versioning

C’est à ce moment que les systèmes de gestion de version distribués entrent en jeu (DVCS en
anglais pour Distributed Version Control Systems). Dans un DVCS (tel que Git, Mercurial,
Bazaar ou Darcs), les clients n’extraient plus seulement la dernière version d’un fichier, mais ils
dupliquent complètement le dépôt.

Ainsi, si le serveur disparaît et si les systèmes collaboraient via ce serveur, n’importe quel dépôt
d’un des clients peut être copié sur le serveur pour le restaurer. Chaque extraction devient une
sauvegarde complète de toutes les données.

De plus, un grand nombre de ces systèmes gère particulièrement bien le fait d’avoir plusieurs
dépôts avec lesquels travailler, vous permettant de collaborer avec différents groupes de
personnes de manières différentes simultanément dans le même projet.

Cela permet la mise en place de différentes chaînes de traitement qui ne sont pas réalisables
avec les systèmes centralisés, tels que les modèles hiérarchiques.
GIT : Système de Gestion de Version Distribué (DVCS)

Bref historique (Wikipedia)

• De 1991 à 2002, le noyau Linux était développé sans utiliser de système de gestion de version.

• A partir de 2002, la communauté a commencé à utiliser BitKeeper, un DVCS propriétaire.

• En 2005, suite à un contentieux, BitKeeper retire la possibilité d'utiliser gratuitement son produit.

Linus Torvalds lance le développement de Git et après seulement quelques mois de développement,
Git héberge le développement du noyau Linux.
Principes de base

Un dépôt Git est une sorte de système de fichiers (base de données), enregistrant les versions de fichiers
d'un projet à des moments précis au cours du temps sous forme d'instantanés.

La différence majeure entre Git et les autres VCS (Subversion et autres) réside dans la manière dont Git considère les données.
Au niveau conceptuel, la plupart des autres systèmes gèrent l’information comme une liste de modifications de fichiers.
Ces systèmes (CVS, Subversion, Perforce, Bazaar et autres) considèrent l’information qu’ils gèrent comme une liste de fichiers
et les modifications effectuées sur chaque fichier dans le temps.

Git ne gère pas et ne stocke pas les informations de cette manière. À la place, Git pense ses données plus comme un
instantané d’un mini système de fichiers. À chaque fois que vous validez ou enregistrez l’état du projet dans Git, il prend
effectivement un instantané du contenu de votre espace de travail à ce moment et enregistre une référence à cet instantané.
Pour être efficace, si les fichiers n’ont pas changé, Git ne stocke pas le fichier à nouveau, juste une référence vers le fichier
original qu’il a déjà enregistré. Git pense ses données plus à la manière d’un flux d’instantanés
GIT

PRINCIPES DE
BASE
3 sections d’un projet GIT :
• Le répertoire Git/dépôt : contient les méta-données
et la base de données des objets du projet.
• Le répertoire de travail : extraction unique d'une
version du projet depuis la base de données du dé
pôt.
• La zone de transit/d'index : simple fichier contenant
des informations à propos de ce qui sera pris en
compte lors de la prochaine soumission.
GIT

PRINCIPES DE
BASE
4 états d’un fichier GIT :
• Non versionné : Fichier n'étant pas ou plus géré par Git
• Non modifié : fichier sauvegardé de manière sûre dans
sa version courante dans la base de données du dépôt ;
• modifié : fichier ayant subi des modifications depuis la
dernière fois qu'il a été soumis ;
• indexé (staged) : idem, sauf qu'il en sera pris un
instantané dans sa version courante lors de la prochaine
soumission (commit).
Principes de base

Chaque soumission (commit) donne lieu à la création d'un objet commit contenant un pointeur vers un
instantané du contenu dont les modifications étaient indexées au moment de la soumission (ensemble
d'objets permettant de stocker
un instantané des fichiers concernés d'une part et de reproduire la structure du
répertoire projet et de ses sous-répertoires d'autre part), quelques méta-données (auteur, message) et un
pointeur vers l'objet commit précédent.
Commandes de base

Initialiser un dépôt

$ git init

Afficher l’état des fichiers du répertoire courant

$ git status

Ø Untracked files : Fichiers non versionnés

Ø Changes to be commited : modifications (ajout, suppression, changements) chargées en zone de transit


(staging area), ou indexées.

Ø Changes not staged for commit : modifications n’ayant pas été chargées en zone de tranzit (ou indéxées)
Commandes de base

Indexer l'ajout ou les changements d'un fichier


$ git add [-p] <fichier>

Annuler les modifications indexées d'un fichier


$ git reset <fichier>

Annuler les modifications non encore indexées d'un fichier


$ git checkout [--] <fichier>

Indexer la suppression d'un fichier


$ git rm <fichier>

Déversionner un fichier
$ git rm --cached <fichier>
Commandes de base

Afficher le détail des modifications non indexées


$ git diff

Afficher le détail des modifications indexées


$ git diff --staged

Soumettre les modifications indexées en zone de transit


$ git commit

Voir l'historique des soumissions


$ git log
GIT : Les BRANCHES

Une branche dans Git est simplement un pointeur léger et déplaçable vers un des commits.
La branche par défaut dans Git s’appelle master. Au fur et à mesure des validations, la branche master
pointe vers le dernier des commits réalisés. À chaque validation, le pointeur de la branche master avance
automatiquement.

Pourquoi les branches ?


• Pouvoir se lancer dans des évolutions ambitieuses en ayant toujours la capacité de revenir à
une version stable que l'on peut continuer à maintenir indépendemment.

• Pouvoir tester différentes implémentations d'une même fonctionnalité́ de manière indé


pendante.
GIT : Les BRANCHES

Créer une nouvelle branche « testing »

$ git branch testing

HEAD est un pointeur spécial vers


branche sur laquelle on travaille
actuellement.
GIT : Les BRANCHES

Voir toutes les branches


$ git branch

Supprimer une branche


$ git branch –d <branche>

Passer à une branche donnée (mise à jour de l’index et du répertoire, ainsi que du pointeur HEAD)
$ git checkout <branche>
GIT : Les BRANCHES

$ git checkout testing

Cela déplace HEAD pour le faire pointer


vers la branche « testing ».
GIT : Branches et Fusion

Prenons un exemple simple faisant intervenir des branches et des fusions (merges) que vous pourriez trouver dans le
monde
réel. Vous effectuez les tâches suivantes :
• vous travaillez sur un site web ;
• vous créez une branche pour un nouvel article en cours ;
• vous commencez à travailler sur cette branche.

À cette étape, vous recevez un appel pour vous dire qu’un problème critique a été découvert et qu’il faut le régler au plus
tôt.
Vous faites donc ce qui suit :
• vous basculez sur la branche de production ;
• vous créez une branche pour y ajouter le correctif ;
• après l’avoir testé, vous fusionnez la branche du correctif et poussez le résultat en production ;
• vous rebasculez sur la branche initiale et continuez votre travail.
GIT : GIT : Branches et Fusion

$ git checkout –b iss53


GIT : GIT : Branches et Fusion

$ vim index.html

$ git commit –a –m « ajout d’un pied de page


[issue53] »

Remarque : La branche iss53 a avancé avec notre travail


GIT : GIT : Branches et Fusion

$ git checkout master

$ git checkout –b hotfix

$ vim index.html

$ git commit –a –m « correction de l’adresse email


…»

Remarque : La branche iss53 a avancé avec notre travail


GIT : GIT : Branches et Fusion

$ git checkout master

$ git merge hotfix


Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)

Remarque : Vous noterez la mention fast-forward (avance rapide) lors du merge.


GIT : GIT : Branches et Fusion

$ git checkout master

$ git merge iss53


Merge made by the 'recursive' strategy.
README | 1 +
1 file changed, 1 insertion(+)
GIT : Branches et Fusion

$ git checkout master

$ git merge iss53


Merge made by the 'recursive' strategy.
README | 1 +
1 file changed, 1 insertion(+)

Remarque: Git réalise une simple fusion à trois sources (three-way merge), en utilisant les deux instantanés pointés par les
sommets des branches ainsi que leur plus proche ancêtre commun.
GIT : Branches et Fusion

Remarque: Au lieu d’avancer simplement le pointeur de branche, Git crée un nouvel instantané qui résulte de la fusion à
trois sources et crée automatiquement un nouveau commit qui pointe dessus.
On appelle ceci un commit de fusion (merge commit) qui est spécial en cela qu’il a plus d’un parent.
GIT : Conflits

En cas de conflit empêchant la fusion :

• Aucun objet commit de fusion n'est créé, mais le processus est mis en pause.

• git status donne les fichiers n'ayant pas pu être fusionnés (listés en tant que unmerged).

• Git ajoute des marqueurs de résolution de conflits à tout fichier sujet à conflits afin que ceux-ci puissent être
résolus à la main.

• Pour marquer les conflits dans un fichier <fichier> comme résolus, il faut faire git add <fichier>. On peut, après
résolution de tous les conflits, soumettre les modifications sous forme d'objet commit de fusion avec git
commit et terminer ainsi le processus de fusion.
GIT : Branches et Rebase

Dans Git, la seconde façon d’intégrer


les modifications d’une branche dans
une autre est le rebasing.

Si vous revenez à un exemple


précédent du chapitre Fusions
(merges), vous remarquerez que votre
travail a divergé et que vous avez ajouté
des commits sur deux branches
différentes.

Pour résoudre ce problème, il existe


une autre approche.
GIT : Branches et Rebase

Pour cela, vous pouvez prendre


le patch de la modification introduite
en C4 et le réappliquer sur C3. Dans
$ git checkout experiment
Git, cette action est appelée "rebaser"
(rebasing).
$ git rebase master
First, rewinding head to replay your work on top of
Avec la commande rebase, vous
it... Applying: added staged command
pouvez prendre toutes les modifications
qui ont été validées sur une branche et
les rejouer sur une autre.
GIT : Branches et Rebase
GIT : Branches et Rebase

À ce moment, vous pouvez retourner sur la branche master et


réaliser une fusion en avance rapide (fast-forward merge).
GIT : Branches et Rebase

Vous pouvez aussi faire rejouer votre rebasage sur autre chose qu’une branche.
Prenez un historique tel que vous avez créé une branche thématique (serveur) pour ajouter des fonctionnalités
côté serveur à votre projet et avez réalisé un commit.

Ensuite, vous avez créé une branche pour ajouter des modifications côté client (client) et avez validé
plusieurs fois. Finalement, vous avez rebasculé sur la branche serveur et avez réalisé quelques commits
supplémentaires.
GIT : Branches et Rebase
GIT : Branches et Rebase

Supposons que vous décidez que vous souhaitez fusionner vos modifications du côté client dans votre ligne
principale pour une publication (release) mais vous souhaitez retenir les modifications de la partie serveur
jusqu’à ce qu’elles soient un peu mieux testées. Vous pouvez récupérer les modifications du côté client qui ne
sont pas sur le serveur (C8 et C9) et les rejouer sur la branche master en utilisant l’option --onto de git rebase :

$ git rebase –onto master server client

Cela signifie en substance "Extraire la branche client, déterminer les patchs depuis l’ancêtre commun des
branches client et serveur puis les rejouer sur master ".
GIT : Branches et Rebase
GIT : Branches et Rebase

$ git checkout master

$ git merge client


GIT : Dépôts distants

Pour collaborer, il est nécessaire de communiquer et d'échanger avec un ou plusieurs dépôts distants hébergeant le
même projet (typiquement des dépôts publics associés à une personne, une équipe ou tout le projet).

Les données des dépôts distants (objets commités et instantanés) sont enjèrement copiées dans le dépôt local, et
chaque branche <branche> d'un dépôt distant <dépôt> est maintenue une branche locale <dépôt>/<branche> non
modifiable, permettant de suivre la position de <branche> sur le <dépôt> localement.

Afficher tous les dépôts distants


$ git remote

Cloner un dépôt distant (automatiquement appelé « origin »)


$ git clone <URL> [<répertoire>]
GIT : Dépôts distants
GIT : Dépôts distants

Récupérer les modifications d’un dépôt distant


$ git fetch <dépôt>
GIT : Dépôts distants

Ajouter un dépôt distant


$ git remote add <nom> <URL>
GIT : Dépôts distants

Mettre à jour un dépôt distant donné pour une certaine branche locale
$ git push <dépôt> <branche>

Attention : ceci fonctionne uniquement si le dernier objet « commit » de la branche concernée du dépôt distant a été
récupéré et intégré dans la branche en question du dépôt local, en d'autres termes si la mise à jour de la branche du
dépôt distant peut être faite par fast-forward.

Combiner git fetch et git merge


$ git pull <dépôt> <branche>

Combiner git fetch et git rebase


$ git pull --rebase <dépôt> <branche>
GIT : Autres commandes

Configuration initiale de git


$ git config --global user.name « John Doe »
$ git config --global user.email « johndoe@example.com »

Afficher les 2 derniers commits


$ git log -n 2

Afficher les logs sur une seule ligne


$ git log --oneline

Afficher les logs d’un fichier


$ git log -p <fichier>
GIT : Autres commandes

Revenir à un commit particulier


$ git checkout « id »

Remettre un fichier à l’état d’un commit précédent


$ git checkout « id » <fichier>

Supprimer les modifications faites lors d’un commit précédent


$ git revert « id »

Supprimer les modifications faites lors d’un commit précédent sur un fichier
$ git revert « id » « fichier »

Remarque : Lors d’un revert, l’historique n’est pas modifié


GIT : Autres commandes

Revenir à un commit particulier (sans supprimer les modifications faites après)


$ git reset « id »

Supprimer toutes les modifications faites et revenir un commit en arrière


$ git reset HEAD^ --hard

Revenir au dernier commit


$ git reset --hard
Exemples de Git Repositories