Gestion de version pour le développement en équipe

Les outils de gestions de version se sont imposés comme l’outil central d’un l’écosystème des technologies utilisées pour la réalisation de projets de développement en informatique.

Ces outils sont en particulier utiles pour le travail en équipe.

Beaucoup de plateformes Web dédiées au développement de projets en équipe ont la gestion de version au centre de leurs applications. (Github, BitBucket, GitLab, SourceForge).

Différents types d’outils de gestions de version existent. C’est depuis l’apparition de la dernière famille d’outils (les gestionnaires de version distribués) que l’écosystème de développement en équipe s’est vraiment développé (Github, BitBucket, GitLab).

Introduction au systèmes de gestion de version

une bonne introduction a GIT se trouve dans le livre Pro Git book par Scott Chacon (CC BY-NC-SA 3.0). Ce cours s’inspire grandement des chapitres 1 à 3 de ce livre.

Quelques définitions

Diff
Diff désigne à la fois le nom de la commande et celui du résultat produit. Le diff permet de visualiser la différence textuelle, ligne par ligne, entre 2 fichiers. Quand on compare deux versions d’un même fichier, le diff donne la liste des modifications pour passer de la première version à la seconde.

Exemple. On a un fichier hello_wold.c :

void main()
{
  printf("Hello World!\n");
}

et le fichier hello_wold2.c:

#include <stdio.h>

int main()
{
  printf("Hello World!\n");
  return 0;
}

Le diff entre hello_wold.c et hello_wold2.c donne :

diff --git a/hello_world.c b/hello_world2.c
index 14049e2..73c3748 100644
--- a/hello_world.c
+++ b/hello_world2.c
@@ -1,6 +1,8 @@
-void main()
+#include <stdio.h>
+
+int main()
 {
     printf("Hello World!\n");
-
+      return 0;
 }

Dépôt
Le dépôt (repository) représente plus ou moins la totalité de la basse de données que représente un système de gestion de version. Le dépôt contient toutes les versions (tout l’historique) d’un projet.
Copie de travail
La copie de travail (working copy, directory) représente le système de fichiers actuelle du projet (l’ensembles des fichiers dans le dossier et les sous-dossier du projet).
Instantané
L’instantané (Snapshot) est l’état ponctuel des fichiers d’un système de fichiers (projet, dossier, sélection de fichiers, etc.). Il représente son contenu, à un moment donnée.
Commit
Un commit (validation), représente un ensemble de changements réalisés sur le dépôt (repository) et qui constitue une nouvelle version atomique du dépôt.
Branche
Un ensemble de validations (commits) ayant divergé de la branche d’origine.
Système de gestion de version
Un système de gestion de version est donc constitué d’au moins un dépôt (repository) et d’une copie de travail (directory). L’ajout de nouvelles versions dans le système se fait grâce à la création de validations (commits) qui sont constitué de diffs entre les instantanés d’un commit précédent et de la copie de travail.

Les systèmes de gestion de version.

Historique des systèmes de gestions de version

il y a 3 grandes familles systèmes de gestion de version :

les Systèmes locaux (Version Control Systems)

Copie manuelle de fichiers locaux.

Local Version Control Systems.

Systèmes de gestion de version centralisés

Un serveur central accessible sur le web contient le dépôt. Les utilisateurs ne possèdent que des copies de travail.

Systèmes de gestion de version centralisés.

Systèmes de gestion de version distribués

Chaque utilisateur possède toute le dépôt (les banches, les commits, etc.) en local.

Il n’y a pas de serveur central. N’importe qui (avec une connexion internet entrante) peut devenir un serveur.

Systèmes de gestion de version distribués.

GIT : 3 états / 3 zones / 3 actions

Dans un dépôt GIT un fichier peut avoir 3 états différents :

Ces états correspondent à 3 zones dans un GIT :

Le passage entre ses 3 états se fait par 3 actions:

configuration de git

une commande pour configurer GIT : git config.

git config --list

Trois niveaux de configuration :

L’authentification est le paramètre de configuration le plus important qu’il ne faut pas négliger.

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

Manipulations de bases avec GIT

Créer un nouveau dépôt

Souvent on dispose déjà d’un projet existant avec du code déjà écrit avant de décider d’en faire le suivit de version.

git init initializes a new repository.

cd myProject
git init
git add "*.java"
git commit -m "Initial commit for myProject"

Récupérer un dépôt existant

La commande git clone fait plusieurs choses :

$ git clone https://github.com/pigne/CountDownWebApp.git

plusieurs protocoles de transfère :

Vérifier l’état des fichiers

la commande la plus utile : git status.

$ git status
# On branch master
nothing to commit (working directory clean)

Commencer le suivit d’un fichier

On utilise la commande git add.

$ git status
On branch master
Initial commit
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	AUTHORS
nothing added to commit but untracked files present (use "git add" to track)
$ git add AUTHORS
$ git status
On branch master
Initial commit
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   AUTHORS

Ignorer des fichiers

Certains fichiers n’ont pas leur place dans le dépôt. Pour tant ils existent dans la copie de travail.

Le fichier .gitignore contient des expressions rationnels qui vont filtrer les fichiers a ignorer :

target/
.projets
.settings/
.classpath
*.class
*~

Valider les modifications

La commande git commit va faire un instantané (snapshot) des modification sélectionnées (staged) pour créer une validation (un commit) et l’insérer das le dépôt.

La validation a toujours besoin d’un message.

Supprimer un fichier

suppression du dépôt et du système de fichier

 git rm readme.txt

Suppression du dépôt mais le fichier reste dans la copie de travail.

 git rm --cached readme.txt

Il faudra une valdation (commit) pour que la suppression soit prise en compte.

Déplacer des fichiers

$ git mv file_from file_to

Historique des validations

$ git log
$ git help log

Better use graphical tools to see git history:

Se déplacer dans les différents états du fichier

Files States

Annuler des validations

la commande git resetpermet de modifier les validations du dépôt.

Annuler le dernier commit mais garder les modifications en local.

$ git reset HEAD~1

Git Commit Commands

Remotes

Pour pouvoir collaborer on a besoin d’un site distant avec lequel échanger les modifications.

On va échanger les commits entre le dépôt local et le/les dépôts distants.

La commande git remote permet de manipuler de dépôts distants (remotes)

$ git clone https://github.com/pigne/CountDownWebApp.git
$ cd CountDownWebApp
$ git remote -v
origin	https://github.com/pigne/CountDownWebApp.git (fetch)
origin	https://github.com/pigne/CountDownWebApp.git (push)

Ajouter: git remote add [shortname] [url]

Récupérer les modifications d’un remote

git fetch [remote-name] va télécharger les nouveaux commits du dépôt distant dans le dépôt local.

git fetch ne modifie que le dépôt local, pas la copie de travail.

Pour réellement mixer les validation des 2 dépôts on utilise git merge

la commande git pull va utiliser fetch et merge

Envoyer les modifications vers un remote

git push [remote-name] [branch-name]

Souvent le remote par défaut est “origin” branche par défaut est “master

$ git push origin master

Git Push/Pull Commands

Les branches

Le dépôt peut se représenter comme un réseau de validations (commits)

Les validations sont identifiées par :

Commits Linked with their parents

Les branches sont des pointeurs

Une branche c’est un pointeur sur une validation.

La branche par défaut s’appelle souvent master.

La commande git branchpermet la manipulation des branches.

HEAD est un pointeur particulier qui indique la branche actuellement utilisée dans la copie de travail.

Branches and HEAD Point to commits

Travailler dans les in branches

git checkout <branch-name> déplace le pointeur HEAD vers la branche indéquée et récupère in instantané (snapshot) du dernier commit de la branche dans la copie de travail.

$ git checkout cli_branch  # moves HEAD
$ # modify some_file
$ git add some_file
$ git commit # moves cli_branch & HEAD

Commits in branches

Branches divergentes

Faire des validations dans plusieurs branches les fait diverger.

$ git checkout master  # moves HEAD
$ # modify some_file
$ git add some_file
$ git commit # moves master & HEAD

Diverging History

Fusionner Branches

As soon as concurrent modifications are finished, we want to reintegrate branches with git merge

Qaund les modificationsn et ajouts sont terminés dans la branche thématique, on va souhaiter réintégrer la branche principale.

$ git checkout master       ## be sure we are in destination branch
$ git merge cli_branch
$ git branch -d cli_branch  ## remove cli_branch as it is useless

Diverging History

Resolving conflicts

In case of conflict the commit is aborted and problematic files are unmerged

En cas de conflit, la fusion est mise en pause. La validation est annulée. Les fichiers concernés par les conflits sont marqués comme non fusionnés (unmerged).

$ git status
index.html: needs merge
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   unmerged:   index.html
#
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
  please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

Remote branches

Remote branches are references to the state of branches on your remote repositories. They’re local branches that you can’t move.

$ git push origin cli_branch
$ git fetch origin
$ git checkout -b bogus123 origin/fix_bug_123