P22 - Qualité de développement

1 - Les bases de Git

Adrien Krähenbühl IUT Robert Schuman

Pourquoi utiliser Git ?

Git est un outil avant tout fait par des développeurs (Linus Torvald, 2005) pour des développeurs.

Git permet :

  1. de suivre l’évolution de votre code,
  2. de pouvoir travailler à plusieurs sur le même code,
  3. de pouvoir partager facilement votre code avec le monde entier.

C’est l’outil n°1 du travail collaboratif, essentiel à maîtriser pour tout développeur qui se respecte.

Il existe d’autres outils similaires… qui tombent en désuétude :

Git, c’est quoi ?

Git est un logiciel de gestion de versions décentralisé.

Gestion de version ?
Le principe consiste à conserver un historique des versions successives d’une arborescence de fichiers afin de pouvoir suivre et manipuler leur évolution dans le temps.
Décentralisé ?
Il n’y a pas un endroit unique de stockage de l’historique des version. Chaque copie d’une arborescence versionnée contient l’intégralité de l’historique.

Graphe et commits

L’historique d’un répertoire se représente sous la forme d’un graphe.

Chaque nœud est appelé commit et contient :

  • une vue instantané (snapshot) de l’état du répertoire à un moment précis
  • des métadonnées : message, auteur, date de création, etc.

Comment ça fonctionne physiquement ?

Git sauvegarde l’ensemble des commits dans un répertoire .git à la racine de cette arborescence.

Pour pouvoir manipuler une arborescence, Git se base sur 3 éléments :

  1. Son historique stocké dans le répertoire .git
  2. Le reste de l’arborescence (qui constitue l’état courant)
  3. D’éventuelles copies distantes de l’arborescence

Les commandes du jour

La liste des commandes documentées est ici : https://git-scm.com/docs


  • git init : Initialise un répertoire géré par Git.
  • git config : Configure le comportement de git.
  • git status : Affiche l’état courant des fichiers.
  • git add : Ajoute des fichiers au prochain commit.
  • git commit : Crée un snapshot.
  • git log : Visualise l’historique, i.e. le graphe des commits
  • git restore : Annule des modifications.
  • git rm/git mv : Supprime/déplace un fichier.
  • git checkout : Charge l’état d’un commit précis.

Initialiser un répertoire Git

Git init

git init
Crée un répertoire .git (le dépôt) dans le répertoire courant.
$ cd /chemin/vers/mon/repertoire/de/base

$ git init
Initialized empty Git repository in /chemin/vers/mon/repertoire/de/base/.git/

$ ls -a
.git
git initDossier
Crée un répertoire Dossier qui contient uniquement le répertoire .git.
$ git init monRepertoireDeBase
Initialized empty Git repository in /chemin/vers/monRepertoireDeBase/.git/

$ cd MonRepertoireGit

$ ls -a
.git

Git config

git config[--global] user.name <myname>
Indique d’utiliser myname comme nom d’auteur des commits
git config[--global] user.email <myemail>
Indique d’utiliser myemail comme email de l’auteur des commits
git config[--global|--local] -l
Liste les options de configuration qui s’applique à cet endroit
$ git config user.name "Adrien Krähenbühl"

$ git config -l
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
user.name=Adrien Krähenbühl
$ cat .git/config
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[user]
    name = Adrien Krähenbühl
  • L’indication --global est à utiliser pour que la configuration soit valable pour tous les dépôts de l’ordinateur.
  • Si la configuration n’est pas globale, alors elle est stockée dans le fichier .git/config
  • Une config. locale est prioritaire sur la config. globale.
  • Il y a BEAUCOUP d’options de configuration pour Git !

Versionner avec Git

Trois zones principales

Le répertoire de travail (working directory) est le répertoire sur le disque dur. Les fichiers y sont créés/modifiés/supprimés.

La zone de transit (staging area) ou index, est un espace temporaire qui stocke les modifications qui seront commitées.

Le dépôt (répertoire .git) stocke tous les commits.

Les commandes git qui suivent vont permettre de manipuler les fichiers pour les faire passer d’une zone à une autre.

Git status

git status affiche les infos sur l’état courant des fichiers.

$ git status
On branch master
Changes to be committed:
        new file:   NouvelleClasse.java
        modified:   README.md

Changes not staged for commit:
        modified:   Diagramme.puml

Untracked files:
        Test.java
  • Changes to be committed liste les fichiers dans la zone de transit.
  • Changes not staged for commit liste les fichiers du répertoire de travail qui ont été modifiés depuis le dernier commit.
  • Untracked files liste les fichiers qui ne sont pas versionnés.

Git add

git add
permet d’ajouter un fichier à la zone de transit, qu’il soit déjà versionné ou non.
$ git add MaClasse.java

$ git status
On branch master
Changes to be committed:
        modified:   MaClasse.java

Git commit

git commit[-m "message"]
Permet d’enregistrer un nouvel instantané dans le dépôt avec un message indiquant en quoi consiste les modifications.
$ git status
On branch master
Changes to be committed:
        modified:   MaClasse.java

$ git commit -m "Ajout du fichier Maclasse.java"

$ git status
On branch master
nothing to commit, working tree clean

Git log

git log[--oneline] [--graph] [--branches]

Liste les commits avec leurs métadonnées :

  • --oneline : chaque commit sur une seule ligne (version condensée)
  • --graph : visualisation du graphe
  • --branches : visualisation de toutes les branches
$ git log
commit 638c310fa5a42839595e9d8499fdb98773feff5e (HEAD -> master)
Author: Adrien Krähenbühl <krahenbuhl@unistra.fr>
Date:   Tua Jan 11 10:02:59 2022 +0100

    Ajout du fichier Maclasse.java

$ git log --oneline
638c310 (HEAD -> master) Ajout du fichier Maclasse.java

Git restore

git restore<file>
annule des modification de qui ne sont pas dans la zone de transit
\(\rightarrow\) le fichier est modifié sur le disque dur.
$ cat MaClasse.java
class MaClasse {}

$ git status
On branch master
Changes not staged for commit:
    modified:   MaClasse.java

no changes added to commit

1. Depuis le dernier commit, MaClasse.java a été modifié.

$ git restore MaClasse.java

$ cat MaClasse.java

$ git status
On branch master
nothing to commit, working tree clean


2. Après git restore, les modifications sont annulées.

Git restore - staged

git restore--staged <file>
désindexe les modifications de <file>, i.e. les retire de la zone de transit. \(\rightarrow\) le fichier n’est pas modifié sur le disque dur
$ cat MaClasse.java
class MaClasse {}

$ git status
On branch master
Changes to be committed:
    modified:   MaClasse.java

1. Depuis le dernier commit, MaClasse.java a été modifié et indexé.

$ git restore --staged MaClasse.java

$ cat MaClasse.java
class MaClasse {}

$ git status
On branch master
Changes not staged for commit:
    modified:   MaClasse.java

no changes added to commit

2. Modifications désindexées.

Git rm / Git mv

git mv<file> <destination

déplace <file> vers <destination>

$ git mv MaClasse.java MaClasse2.java
$ git statusOn branch master
Changes to be committed:
renamed:    MaClasse.java -> MaClasse2.java
git rm<file>

supprime <file>

$ git rm MaClasse.java
$ git status
On branch master
Changes to be committed:
deleted:    MaClasse.java
  • les fichiers versionnés doivent être manipulés exclusivement avec git : pas d’explorateur, pas de commande système.
  • ces commandes sont effectuées pour Git ET le système de fichier

Tableau récapitulatif

Manipuler l’histoire
(de git)

Des commits… mais pourquoi faire ?

Toute la partie précédente montre comment créer des commits en gérant les fichiers présent dans le répertoire de travail.

On peut obtenir un historique comme celui-ci :

$ git log --oneline --graph
* 56dd655 (HEAD -> master) Suppression de MaClasse.java
* eaa13b4 Ajout de README.md
* 6d865ec Ajout de Diagramme.puml
* 638c310 Ajout du fichier Maclasse.java


Voyons comment voyager dans le temps…

Git checkout

git checkout<commit-id>
Met le répertoire de travail dans l’état du commit d’identifiant unique <commit-id> (calculé par la fonction de hachage SHA-1)
1 - État Initial
$ git log --oneline --graph
* 56dd655 (HEAD -> master) Suppression de MaClasse.java
* eaa13b4 Ajout de README.md
* 6d865ec Ajout de Diagramme.puml
* 638c310 Ajout du fichier Maclasse.java
$ ls
Diagramme.puml  README.md

2 - “Voyage” vers le commit d’identifiant 6d865ec

$ git checkout 6d865ec
HEAD is now at 6d865ec Ajout de Diagramme.puml
3 - État après déplacement
$ git log --oneline --graph
* 6d865ec (HEAD) Ajout de Diagramme.puml
* 638c310 Ajout du fichier Maclasse.java
$ ls
Diagramme.puml  MaClasse.java

Le pointeur HEAD

  • Git utilise un pointeur nommé HEAD pour indiquer où il se trouve dans le graphe des commits.
  • La commande git commit fait en réalité deux choses :
    1. Enregistrer un nouveau commit
    2. Déplacer le pointeur HEAD sur ce nouveau commit
  • La commande git checkout déplace uniquement le pointeur HEAD sur un commit donné en argument.


1 - Départ

2 - git commit -m "..."

3 - git checkout 6d865ec

La suite





Au prochain CM : les branches !