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
  • les systèmes centralisés
  • les systèmes décentralisés

les Systèmes locaux (Version Control Systems)

Copie manuelle de fichiers locaux.

  • + Facile à utiliser.
  • - Facile de se tromper.
  • - Pas de travail en équipe.
  • outils: rcs

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.

  • + Travail en équipe.
  • - Un point de vulnérabilité unique (si le serveur tombe personne ne peux travailler).
  • - la plupart des opérations (diff, logs, historique) requière un accès réseau (lent).
  • outils: CVS, Subversion

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.

  • + Pas de vulnérabilité unique.
  • + La plupart des opérations sont en local (diff, historique, logs, manipulation de branches, etc.). Pas de connexion réseau nécessaire (plus rapide)
  • + Thousands of branches can be gracefully handled.
  • tools: Git, Mercurial, Bazaar or Darcs

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 :

  • Modifié (modified): il a des modification locales, il va falloir le sélectionner (stage) pour ensuite valider (commit) ses modifications.
  • Sélectionné (staged): ses modification ont été sélectionnées (staged) pour être validées (commited).
  • Validé (commited): il est synchrone avec le dépôt et ne requière pas de validation.

Ces états correspondent à 3 zones dans un GIT :

  • La copie de travail (directory), c’est le système de fichier local, zone où les fichiers sont modifiés.
  • La zone de sélection (staging area)
  • Le dépôt où les modifications sont enregistrées sous forme de validations (commits).

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

  • Sélection (stage) qui sélectionne les fichier pour la validation(commande : git add).
  • Validation (commit) qui crée le commit et l’envoie dans le dépôt (commande: git commit).
  • Récupération (checkout) qui récupère un instantané (snapshot) depuis le dépôt vers la copie de travail (commande : git checkout).

configuration de git

une commande pour configurer GIT : git config.

git config --list

Trois niveaux de configuration :

  • the system level : --system option, modifies /etc/gitconfig
  • the user level : --globaloption, modifies ‘~/.gitconfig’
  • the repository level : no option, modifies .git/config

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 :

  • elle télécharge le dépôt à partir d’une url distante (le remote)
  • elle récupère (checkout) la dernière validation (commit) dans la copie de travail.
  • elle enregistre l’url passée en paramètre comme étant le dépôt distant par défaut.
$ git clone https://github.com/pigne/CountDownWebApp.git

plusieurs protocoles de transfère :

  • git://,
  • http(s)://,
  • user@server:/path.git.

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.

  • Start editing a file… Say AUTHORS
  • Check the status with git status
$ 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)
  • Start tracking with git add
$ 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.

  • les fichiers compilés (\*.class, \*.o, Eclipse’s bin folder),
  • les dépendances externes (\*.jar, \*.so, node_modules/)
  • les archives de déploiement (\*.tar, \*.jar, \*.war),
  • les logs et sauvegardes (\*.log, \*~),
  • les fichiers de paramètres des IDE / éditeurs (Eclipse’s .settings/ .classpath .project).

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.

  • git commit sans l’option -m va ouvrir l’éditeur de texte.
  • git commit -m "My commit message that details what happens here..."pour donner un message en ligne.

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:

  • Linux : git-cola, gitg, git gui, qgit, SmartGit
  • Mac / Windows : github GUI
  • IDEs usually have good GIT support.

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 :

  • un code de contrôle unique (check-sum)
  • un/des liens vers un/des commits parents.

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.

  • Pour fusionner la branche B dans la branche A on doit fait appel à la commande merge depuis la branche A
  • La fusion de 2 branches peut :
    • générer un conflit si les modifications sont incompatibles (e.g. modification des mêmes lignes de code),
    • générer une validation (commit) automatique si les modifications peuvent se fusionner automatiquement (e.g. modification de lignes différentes qui n’entrent pas en conflit)
    • l’intégration des validations de la branche B dans A sans validation de fusion (merge commit) si ocune fusion n’est nécessaire (e.g. modification de fichiers différents).
$ 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
#
  • On peut utiliser git mergetool pour appeler l’utilitaire de fusion de fichiers (kdiff3,tkdiff,xxdiff,meld,gvimdiff,opendiff,emerge,vimdiff).
  • Ou éditer les fichiers non fusionnés à la main
<<<<<<< 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
  • At the end re-stage files and commit.

Remote branches

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

  • A remote branch is denoted as [remote_name]/[branch_name] (e.g. origin/master)
  • git clone will set local master according to origin/master
  • when you commit on master but do not “push”, then you are “ahead”.
  • We can push a local branch to a remote:
$ git push origin cli_branch
  • We can create a new local branch that “tracks” a remote one:
$ git fetch origin
$ git checkout -b bogus123 origin/fix_bug_123
  • any git pull or git push from the branch bogus123 will refer to remote origin with branch fix_bug_123.