Objectifs de certification

DEVASC 200-901


Gestionnaire de version Git

Dans le cadre de l’Infrastructure as Code, DevOps, du déploiement d’applications par l’orchestration de conteneurs sur du cloud hybride, etc., les ressources et leur configuration sont présentées sous forme de code source. L’hébergement du code source dans un référentiel Git est souvent un pré-requis et au minimum une bonne pratique de gestion.

1. Gestionnaires de version

La gestion de versions (en anglais : version control ou revision control) consiste à gérer l’ensemble des versions d’un ou plusieurs fichiers (généralement en texte). Essentiellement utilisée dans le domaine de la création de logiciels, elle concerne surtout, mais pas nécessairement, la gestion des codes source.

1.1. Code source

Le code source est un ensemble de codes écrits généralement en texte brut dans un langage de programmation conçu et lisible par des humains. Le code source d’un programme indique les actions à effectuer par un ordinateur. Le code source est souvent transformé par un compilateur en code machine binaire qui peut être exécuté par un ordinateur. Le code machine peut ensuite être stocké pour être exécuté ultérieurement. Alternativement, le code source peut être interprété et donc exécuté immédiatement.

1.2. Gestionnaires de version centralisés

Avec les logiciels de gestion de versions centralisée, comme CVS et Subversion (SVN), il n’existe qu’un seul dépôt des versions qui fait référence, sur un serveur central.

1.3. Gestionnaires de version distribués

La gestion de versions décentralisée permet à chacun de travailler à son rythme, de façon désynchronisée des autres, puis d’offrir un moyen à ces développeurs de s’échanger leur travaux respectifs.

En effet, il existe plusieurs dépôts pour un même code. Les clients n’extraient plus seulement la dernière version d’un fichier, mais ils dupliquent complètement le dépôt.

Par exemple, GNU Arch, Git et Mercurial sont des logiciels de gestion de versions décentralisés.

2. Git

Git est une implémentation open source d’un système de contrôle de version distribué créé par Linus Torvalds, l’auteur du noyau Linux.

2.1. Avantages de Git

Parmi ses nombreux avantages, on peut citer :

  • Facilité d’apprentissage
  • Gestion de tous les types de projets, y compris les projets de grandes entreprises
  • Performances rapides
  • Conçu pour les projets collaboratifs
  • Flexible
  • Faible empreinte
  • Dispose de tous les avantages d’un système de contrôle de version distribué
  • Gratuit

2.2. Installation d’un client Git

Un client Git doit être installé sur la machine cliente. Il est disponible pour macOS, Windows et Linux/Unix. Bien que certains clients Git viennent avec une interface graphique de base, Git se concentre sur l’interface de ligne de commande.

On trouvera les binaires et les méthodes d’installation sur le site Git-SCM ainsi que des interfaces graphiques (GUI).

Pour Windows on conseillera volontiers l’installation de l’implémentation pour Windows de Git “Git for Windows”.

Pour une expérience native sous Windows qui se rapproche de l’expérience Linux, on conseillera Windows Terminal à installer à partir du Microsoft Store et le gestionnaire de paquets Chocolatey :

choco install git.install

Sur les systèmes Unix/Linux :

{yum,dnf,apt,brew} install git

Pour la suite des exercices, les logiciels suivants sont nécessaires :

{yum,dnf,apt,brew} install -y vim curl unzip

3. Configuration de Git

La comportement de Git est contrôlé par la commande git config sous forme de variables.

3.1. Emplacement de la configuration de Git

Ces variables de configuration sont enregistrées dans trois emplacements distincts dans l’ordre de précédence :

EmplacementPortéeCommande git
.git/configpour le dépôt courant seulementgit config
~/.gitconfigpour l’utilisateur courantgit config --global
/etc/gitconfigpour tous les utilisateurs du systèmegit config --system

Git contient un outil appelé git config pour vous permettre de voir et modifier les variables de configuration qui contrôlent tous les aspects de l’apparence et du comportement de Git.

3.1. Configuration de l’identité

La première étape est la configuration de son nom et de son adresse de courrier électronique (veuillez adapter l’exemple) :

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

3.2. Configuration de l’éditeur de texte

Il peut être utile de définir l’éditeur de texte par défaut que Git va utiliser, ici vim :

git config --global core.editor vim

3.3. Vérifier les paramètres

Pour vérifier les paramètres de configuration de l’utilisateur courant :

git config --list
user.name=John Doe
user.email=johndoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...

On peut interroger git sur un paramètre particulier, ici user.name :

git config user.name
John Doe

3.4. Obtenir de l’aide

On peut obtenir les pages manuel de Git de plusieurs manières :

git help <commande>
git <commande> --help
man git-<commande>

Par exemple, on peut voir la page de manuel pour la commande config comme ceci :

git help config

4. Commencer un projet Git

On peut commencer un projet Git à partir :

  • d’un projet existant ou copié en l’important dans Git,
  • d’un référentiel existant, en le “clonant” (voyez plus bas le point “Travailler avec des dépôts distants”).

4.1. Initialiser un référentiel Git dans un dossier existant

Pour transformer un dossier de code source en référentiel Git, il suffit de valider la commande git init dans le dossier du projet.

Imaginez que vous vouliez créer un projet avec le code zippé sur https://github.com/cisco-goffinet-org/hello_network/archive/master.zip, voici la procédure.

On télécharge le code, on le décompresse et on se rend dans le dossier du code :

curl -L https://github.com/cisco-goffinet-org/hello_network/archive/master.zip -o hello_network.zip
unzip hello_network.zip
cd hello_network-master
ls -a
.  ..  .gitignore  hello_network.py  hello_network.sh  LICENSE  README.md

On crée un référentiel Git :

git init

La commande nous indique qu’un dossier caché .git/ est créé :

Dépôt Git vide initialisé dans ./hello_network-master/.git/

Désormais le dossier courant devient le dossier de travail qui est un instantané de la base de donnée du référentiel situé dans ce dossier .git/.

4.2. Composants d’un projet Git

Git est une sorte de système de fichier capable de gérer des versions sous forme d’instantané d’un système de fichiers.

Un “référentiel”, un “dépôt” ou un “projet Git” contient trois sections principales :

  1. le dossier .git/ qui contient les méta-données et la base de données des objets du référentiel. C’est que l’on télécharge quand on clone un projet.
  2. le “Working Directory”, le dossier de travail, est l’extraction unique de la base de donnée des objets du projet prêts à être modifiés. C’est ce que l’utilisateur voit de la représentation en système de fichier de son projet.
  3. La “Staging area”, la zone d’index, la zone de préparation est un simple fichier, généralement situé dans le répertoire .git/ qui enregistre ce qui fera partie des prochains instantanés.

4.3. Worflow habituel d’un projet Git

Le worflow habituel d’un dépôt Git déjà initialisé est le suivant :

  1. Un fichier du projet dans le dossier de travail local est modifié.
  2. Le fichier peut alors être ajouté à la zone d’index (staging) car il sera “suivi”, c’est-à-dire qu’il fera probablement partie du prochain instantané, soit la prochaine version du projet. C’est la commande git add qui intervient ici.
  3. Le fichier indexé sera inclus au prochain instantané en le validant, faisant ainsi en sorte que les instantanés des fichiers de l’index soient déplacés dans la base de données du répertoire .git/ devenant ainsi la dernière version. Cette version est représentée par une signature SHA-1. Ce sera la commande git commit qui interviendra ici.

4.4. Fichier non suivi, suivi, inchangé, modifié, et indexé

Souvenons-nous que chaque fichier de la copie de travail peut avoir deux états nous dit le Livre GIT-SCM : “sous suivi” de version ou “non suivi” :

  • Les fichiers “suivis” sont les fichiers qui appartenaient déjà au dernier instantané ; ils peuvent être inchangés, modifiés ou indexés.
  • Tous les autres fichiers sont “non suivis”, soit tout fichier de votre copie de travail qui n’appartenait pas à votre dernier instantané et qui n’a pas été indexé.

Dans un dépôt fraichement “cloné”, “tous les fichiers seront sous suivi de version et inchangés car Git vient tout juste de les extraire et vous ne les avez pas encore édités”.

Workflow Git

Le processus consiste donc à effectuer des modifications, à indexer les fichiers modifiés et puis à les valider dans une version du code, et ainsi de suite.

5. Travailler sur un dépôt Git local

5.1. Vérifier l’état des fichiers

C’est la commande git status qui permet de vérifier le statut des fichiers dans la copie de travail :

git status

Voici ce que vous devriez voir :

Sur la branche master

Aucun commit

Fichiers non suivis:
  (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé)
	.gitignore
	LICENSE
	README.md
	hello_network.py
	hello_network.sh

aucune modification ajoutée à la validation mais des fichiers non suivis sont présents (utilisez "git add" pour les suivre)

Cette sortie nous indique plusieurs choses :

  • “Sur la branche master” : on est sur la branche “master”.
  • Aucun “commit”
  • Fichiers “non suivis”
  • Aucune modification ajoutée à la validation

Manifestement, on trouve cinq fichiers non-suivis et non indexés (puisqu’ils sont nouveaux), c’est-à-dire n’étant pas présents dans le dernier instantané. Il s’agit d’éviter de suivre accidentellement des fichiers binaires par exemple.

5.2. Placer de nouveaux fichiers sous suivi de version

Pour commencer à suivre les nouveaux fichiers, on utilise la commande git add, ici le “point” “.” pour indiquer tout ce qui est dans le dossier parent et ses sous-dossiers :

git add .

On dira alors que les cinq fichiers sont suivis et indexés, prêts à faire partie de la prochaine version.

git status
Sur la branche master

Aucun commit

Modifications qui seront validées :
  (utilisez "git rm --cached <fichier>..." pour désindexer)
	nouveau fichier : .gitignore
	nouveau fichier : LICENSE
	nouveau fichier : README.md
	nouveau fichier : hello_network.py
	nouveau fichier : hello_network.sh

5.3. Indexer des fichiers modifiés

Si on modifie un fichier qui est déjà sous suivi de version LICENSE et que l’on lance à nouveau la commande git status, on verra ceci :

echo "Author: myself" >> LICENSE
git status
Sur la branche master

Aucun commit

Modifications qui seront validées :
  (utilisez "git rm --cached <fichier>..." pour désindexer)
	nouveau fichier : .gitignore
	nouveau fichier : LICENSE
	nouveau fichier : README.md
	nouveau fichier : hello_network.py
	nouveau fichier : hello_network.sh

Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git restore <fichier>..." pour annuler les modifications dans le répertoire de travail)
	modifié :         LICENSE

Le fichier LICENSE sous suivi de version a été modifié dans la copie de travail mais n’est pas encore indexé.

5.4. Fichiers non-suivis

Veuillez imaginer un fichier NOTES qui ne doit pas être suivi, quel est le message git status ?

echo "note 1" >> NOTES
git status
Sur la branche master

Aucun commit

Modifications qui seront validées :
  (utilisez "git rm --cached <fichier>..." pour désindexer)
	nouveau fichier : .gitignore
	nouveau fichier : LICENSE
	nouveau fichier : README.md
	nouveau fichier : hello_network.py
	nouveau fichier : hello_network.sh

Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git restore <fichier>..." pour annuler les modifications dans le répertoire de travail)
	modifié :         LICENSE

Fichiers non suivis:
  (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé)
	NOTES

5.5. Statut court

Les commandes git status -s ou git status --short permettent d’obtenir un affichage plus succinct :

git status -s
A  .gitignore
AM LICENSE
A  README.md
A  hello_network.py
A  hello_network.sh
?? NOTES

On trouve deux colonnes d’état :

  • celle de gauche indique l’état de l’index,
  • celle de droite l’état du dossier de travail.

Les lettres signifient l’état du fichier dans l’index et dans le dossier de travail :

  • ?? : nouveaux fichiers qui ne sont pas suivis
  • A : fichiers nouveaux et indexés
  • M : fichiers modifiés

5.6. Ignorer des fichiers

Pour éviter dans tous les cas qu’un fichier fasse partie d’un suivi de version, on peut le renseigner dans un fichier .gitignore situé à la racine du projet. Par exemple, pour que Git “ignore” le fichier NOTES :

echo "NOTES" >> .gitignore
git status -s
AM .gitignore
AM LICENSE
A  README.md
A  hello_network.py
A  hello_network.sh

Le fichier NOTES a disparu du statut Git ! Le fichier .gitignore a été modifié dans le dossier de travail mais n’a pas été indexé.

On trouvera sur GitHub une liste maintenue d’exemples de fichiers .gitignore en fonction du type de projet : https://github.com/github/gitignore.

Ajoutons les fichiers modifiés à l’index pour validation:

git add LICENSE
git add .gitignore
git status -s
A  .gitignore
A  LICENSE
A  README.md
A  hello_network.py
A  hello_network.sh

6. Valider des modifications et créer des versions

6.1. Valider des modifications

Pour valider les modifications indexées et constiuer une nouvelle version qui correspond à un instantané, on utilise la commande git commit. Git incite aux bonne pratique et nous oblige d’ajouter un commentaire à la validation. Si on lance la commande git commit sans commentaire, l’éditeur de texte par défaut s’ouvre et vous en propose un.

Pour indiquer le commentaire directement dans la ligne de commande, on utilisera l’option -m "commentaire", comme par exemple :

git commit -m "first commit"
[master (commit racine) 6b29a62] first commit
 5 files changed, 158 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 LICENSE
 create mode 100644 README.md
 create mode 100755 hello_network.py
 create mode 100755 hello_network.sh

La sortie nous offre quelques informations comme :

  • la branche validée (master)
  • le somme de contrôle SHA-1
  • le nombre de fichiers et de lignes changée
  • les fichiers créés

6.2. Valider en passer l’étape de mise en index

Pour éviter la phase de placement des fichiers dans la zone d’index, on utilise la commande git commit -a.

Ajoutons une modification au fichier LICENSE :

echo "date: 2021-12-21" >> LICENSE
git status -s
 M LICENSE

Mais la commande git commit -a permet de placer automatiquement tout fichier déjà suivi dans la zone d’index avant de réaliser la validation, ce qui évite le passage par “git add

git commit -a -m "add date to LICENSE"
[[master 68a60c2] add date to LICENSE
 1 file changed, 1 insertion(+)

6.3. Voir l’historique des validations

git log --pretty=oneline
68a60c28df5a57fe630b2da58aafe3d5c694456b (HEAD -> master) add date to LICENSE
6b29a623dd00c454e19ea3161268ed69e0178df0 first commit

7. Inspecter les modifications indexées et non indexées

Pour savoir non seulement quels fichiers ont changé mais aussi ce qui a changé dans ces fichiers, on utilise la commande git diff. On peut donc savoir ce qui a été modifié mais qui n’est pas encore indexé, mais aussi quelle modification a été indexée et est prête pour la validation.

7.1. Inspecter les modifications non indexées

Modifions un fichier suivi :

echo "type: MIT" >> LICENSE

La commande git diff compare le contenu du répertoire de travail avec la zone d’index :

git diff
diff --git a/LICENSE b/LICENSE
index 726ef2d..e6a0486 100644
--- a/LICENSE
+++ b/LICENSE
@@ -21,3 +21,4 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 Author: myself
 date: 2021-12-21
+type: MIT

Ce résultat indique les modifications réalisées mais non indexées.

7.2. Inspecter les modifications indexées

Pour voir les modifications indexées qui feront partie de la prochaine validation, on utilise git diff --cached ou git diff --staged.

La commande git diff --staged compare les fichiers indexés et le dernier instantané :

git diff --staged

Ajoutons à l’index le fichier LICENSE, git diff ne donne pas de résultat :

git add LICENSE
git diff

Mais git diff --staged donne la différence entre l’index et le dernier instantané.

git diff --staged
diff --git a/LICENSE b/LICENSE
index 726ef2d..e6a0486 100644
--- a/LICENSE
+++ b/LICENSE
@@ -21,3 +21,4 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 Author: myself
 date: 2021-12-21
+type: MIT

8. Effacer, annuler

8.1. Effacer des fichiers suivis

Pour effacer un fichier de Git, vous devez l’éliminer de la zone d’index puis valider. La commande git rm -f réalise cette action en effaçant aussi ce fichier de la copie de travail.

git rm -f LICENSE
git status
rm 'LICENSE'
[root@dev1 hello_network-master]# git status
Sur la branche master
Modifications qui seront validées :
  (utilisez "git restore --staged <fichier>..." pour désindexer)
	supprimé :        LICENSE

Lors de la prochaine validation, le fichier sera absent et non-suivi en version.

git commit -m "Remove LICENSE"
[master f89374b] Remove LICENSE
 1 file changed, 23 deletions(-)
 delete mode 100644 LICENSE

8.2. Annuler le dernier commit

git reset --hard HEAD^
HEAD est maintenant à 7795b55 modify LICENSE

8.3. Désindexer un fichier déjà indexé

echo "I made a mistake!" >> LICENSE
git add LICENSE
git status
Sur la branche master
Modifications qui seront validées :
  (utilisez "git restore --staged <fichier>..." pour désindexer)
	modifié :         LICENSE
git restore --staged LICENSE
Sur la branche master
Modifications qui seront validées :
  (utilisez "git restore --staged <fichier>..." pour désindexer)
	modifié :         LICENSE

[root@dev1 hello_network-master]# git restore --staged LICENSE
[root@dev1 hello_network-master]# git status
Sur la branche master
Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git restore <fichier>..." pour annuler les modifications dans le répertoire de travail)
	modifié :         LICENSE

8.4. Réinitialiser un fichier modifié

git status -s
 M LICENSE
git checkout -- LICENSE
git diff
git diff staged

8.5. Ajouter les modifications au dernier commit

git commit --amend -m "new commit"

9. Branches

9.1. Créer une branche

Créer une branche signifie diverger de la ligne principale de développement et continuer à travailler sans impacter cette ligne.

git branch testing
git branch
* master
  testing

9.2. Basculer sur une branche

git checkout testing
Basculement sur la branche 'testing'

9.3. Validation des modifications d’une branche

git checkout testing
echo test > TEST
git add TEST
git commit -m "add TEST"
[testing 69be7b1] add TEST
 1 file changed, 1 insertion(+)
 create mode 100644 TEST

9.4. Fusionner une branche (Merge)

git checkout master
git merge testing
Mise à jour fe3d6c2..9444eef
Fast-forward
 TEST | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 TEST

9.5. Effacer une branche

git branch -d testing
Branche testing supprimée (précédemment 9444eef).

9.6. Fusionner une branche (Rebase)

9.7. Fusionner une branche (Cherry-pick)

10. Créer un référentiel avec un service Git distant

10.1. GitHub, GitLab et beaucoup d’autres

10.2. Installer GitHub CLI

  • Prenez un compte chez Github
  • veuillez installer GitHub CLI.
  • Disposez d’une paire de clés SSH, autrement générez les avec la commande ssh-keygen.

10.3. Configurer GitHub CLI

gh auth login
gh auth refresh -s write:public_key
gh config set editor vim

10.4 Créer un dépôt sur Github

gh repo create
? Repository name hello_network_test
? Repository description
? Visibility Public
? This will add an "origin" git remote to your local repository. Continue? Yes
✓ Created repository cisco-goffinet-org/hello_network_test on GitHub
✓ Added remote https://github.com/cisco-goffinet-org/hello_network_test.git

11. Travailler avec des dépôts distants

11.1. Afficher les dépôts distants

git remote -v
origin	https://github.com/goffinet/hello_network_test.git (fetch)
origin	https://github.com/goffinet/hello_network_test.git (push)

11.2. Pousser son travail sur un dépôt distant

Quand le dépôt semble prêt à être partagé, on peut le pousser sur le serveur distant avec la commande git push [nom-distant] [nom-de-branche]. Ici par exemple la branche master vers le serveur origin :

git push origin master

11.3. Récupérer et tirer depuis des dépôts distants

un git pull sur une de ces branches récupère toutes les références distantes et fusionne automatiquement la branche distante correspondante dans la branche actuelle.

git pull

11.4. Cloner un dépôt git existant

Si le projet Git existe déjà sur un serveur distant, vous pouvez le cloner sur votre machine locale, avec la commande git clone [url], par exemple :

git clone https://github.com/cisco-goffinet-org/hello_network

Un dossier hello_network se crée à l’endroit de l’exécution de la commande git clone et on peut s’y rendre. On constate la présence d’un dossier caché .git/ :

cd hello_network
ls -la

11.5. Cloner un dépôt git en précisant la destination

12. Etiquettes

12.1. Types d’étiquettes

Git utilise deux types d’étiquettes : légères et annotées.

Une étiquette légère ressemble beaucoup à une branche qui ne change pas, c’est juste un pointeur sur un “commit” spécifique.

Les étiquettes annotées sont stockées en tant qu’objets à part entière dans la base de données de Git. Elles ont une somme de contrôle, contiennent le nom et l’adresse e-mail du créateur, la date, un message d’étiquetage et peuvent être signées et vérifiées avec GNU Privacy Guard (GPG).

12.2. Lister les étiquettes

git tag

Créer des étiquettes annotées

On crée des étiquettes annotées avec l’option -a et -m à la commande git tag :

git tag -a v0.1 -m 'ma version 0.1'
git tag

De manière plus détaillée :

git show v0.1

12.3. Créer des étiquettes légères

Les étiquettes légères se réduisent à stocker la somme de contrôle d’un “commit” dans un fichier, aucune autre information n’est conservée. On n’utilise aucune des options -a, -s ou -m de la commande git tag :

git tag v0.1-lg
git tag
v0.1
v0.1-lg

12.4. Étiqueter après un commit

Mettont l’étiquette v0 au commit initial du projet :

git tag -a v0 939dafd1 -m 'v0'
git tag
v0
v0.1
v0.1-lg

12.5. Partager les étiquettes sur le serveur distant

Par défaut, la commande git push ne pousse pas les étiquettes vers les serveurs distants. Il faut explicitement les pousser après les avoir créées localement. Ce processus s’apparente à pousser des branches distantes avec la commande git push origin [nom-du-tag].

git push origin v0

Synthèse sur Git

  • init : Git est une sorte de système de fichiers virtuel (un repo git, un référentiel) pour héberger des fichiers (de code source).
  • add, tag et commit : On soumet une nouvelle version des fichiers qui sont suivis (ajoutés à un index) dans un “commit” représenté par une somme de contrôle comme point de référence. On peut placer des étiquettes sur ces validations de version.
  • branch, switch et checkout : Une branche est une suite de “commits” qui diverge à partir d’un point de contrôle. On peut fusionner des branches de différentes manières (merge, rebase, cherry-pick).
  • push et pull : synchroniser un référentiel local et un référentiel distant.

Tags : ,

Catégories :

Mis à jour :

État d'avancement du document : 70 %