Versionnage avec Git, Démarche agile

Gérard Rozsavolgyi

roza@univ-orleans.fr

Sept. 2022

GitDépôts

florian.groult@univ-orleans.fr roza@univ-orleans.fr

Les systèmes de gestion de version

Git

Formations 2022-2023

Plan et fiches

  • Plan:

    • Notions générales sur les systèmes de gestion de version
    • Git, prise en main
    • Les branches en Git
    • Introduction aux tests

Fiches memo sur Git en pdf

Slides Git en pdf

Autres ressources

Notions Générales

Problématique 1

Conserver l’historique des modifications apportées chaque jour… et revenir en arrière en cas de besoin

Problématique 2

Partager le développement entre plusieurs personnes : - permettre un accès partagé au système de fichiers versionné - permettre un accès distant depuis diverses plateformes - retrouver rapidement l’origine d’un Bug en cas de régression

Problématique 3

Gérer la distribution du logiciel

plusieurs versions peuvent coexister (branches de développement, branches beta, branches production)

Problématique 4

Utiliser de l’intégration continue (Gitlab, Github, Jenkins, etc.)

introduire des vérifications, tests, production d’artefacts lors d’une mise à jour d’un dépôt.

Complexe

Multiples branches à gérer en parallèle …

Ou

Branches de Google Chrome…

Un logiciel de gestion de version

  • Agit sur une arborescence de fichiers
  • Permet de mutualiser un développement
  • Permet de stocker toute évolution du code source

Ajoute une nouvelle dimension au système de fichiers: le temps

2 modèles

  • Centralisés
  • Décentralisés

Centralisés 👹

  • Style CVS ou SVN (subversion)
  • Un seul dépôt de référence
  • Besoin d’un serveur
  • Besoin de synchronisation
  • Conflits plus fréquents…

Décentralisés 🔆

  • Plusieurs dépôts pour un même logiciel
  • Chacun peut travailler à son rythme
  • De façon synchronisée ou pas des autres

Systèmes décentralisés

  • Bazaar
  • Mercurial
  • Git

Avantages ⭐️

  • Indépendant d’une machine
  • Travail sans connexion
  • Participation “progressive” à un projet open source :
    • Accès au code
    • Contribution proposée
    • Si acceptée, contributeur “actif”

Git

  • Le plus utilisé
  • créé par Linus Torvalds pour gérer le noyau de Linux
  • centaines de contributeurs

Historique video Linux Kernel contributions

Première révision par Linus T.

git init premier commit

Concrètement

git xkcd

Git, Github, Gitlab ?

  • git : le logiciel

  • Github, Gitlab, Sourcetree, etc. : Services/hébergeurs utilisant git

Github, Gitlab, etc.

Les entrepôts de code connus

  • Github permet maintenant des dépôts privés gratuits depuis le rachat par Microsoft… Voir
  • Gitlab et bitbucket le permettaient déjà
  • Vous pouvez télécharger et installer votre propre gitlab ou Gogs

Prise en main de git

git help

Documentation

bob> git --help
bob> git help -a # all, afficher toutes les sous-commandes
bob> git help init # aide pour une sous-commande

Création

Création d’un dépôt (repository) vide :

  git init
  • Un dossier .git est créé

  • Pour voir son contenu :

    tree .git

Dépôt 📂

Un dépôt apparaît de l’extérieur comme un système de fichiers composé de répertoires au sein desquels on peut naviguer, lire et écrire selon les permissions dont on dispose.

Dépôt de référence

  • Dépôt contenant les versions livrées d’un projet
  • Un dépôt est un emplacement central où sont stockées :
    • l’historique des versions des fichiers
    • les logs
    • les dates, auteurs, tags, etc.

Configuration

Informe git de l’identité du “commiteur”

alan> git config --global user.name "Alan Turing "
alan> git config --global user.email "alan@univ-orleans.fr"
alan> git config --global core.editor emacs # Par défaut nano ou vim
alan> git config --global core.editor "code --wait" # Pour utiliser correctement vscode

alan> git config -l

Choix de –global ou –local, de l’éditeur, etc.

status

Statut du dépôt git par rapport au système de fichiers, dépôt distant, etc. À utiliser très souvent !

Permet de vérifier :

  • Si vous avez du nouveau contenu à commiter
  • sur quelle branche vous travaillez
  • S’il vous manque du contenu du dépôt distant
  • ou l’inverse : Your branch is ahead of 'origin/master' by 3 commits.

diff

Différences détaillées :

  • entre l’état actuel et le dernier état connu par git (défaut)
  • pareil mais pour un seul fichier en paramètre,
  • entre deux commits, etc.

Avec option --stat, juste le nombre de lignes changées par fichier.

Possible directement en ligne de commande interactive ou par un mergetool (cf merge) ou avec un IDE

Ajout

Pour ajouter un fichier spécifique :

  git add mon_fichier

Pour ajouter tout le contenu du répertoire courant :

  git add .

Fichier dans l’ index (staged) mais pas encore commité

Retrait

Désindexer :

  git restore --staged fichier

Annuler les modifications :

  git restore fichier # si fichier connu par git, desindexer et rm sinon

Effacer :

  git rm fichier

(ou rm fichier puis git add fichier)

Ignorer certains fichiers

  • Ajouter et commiter un nouveau fichier .gitignore
  • Contenant une liste de fichiers ou extensions que vous ne voulez pas versionner. Par exemple :
*.o
__pycache__
*.class
*~

Commit ⛳️

  • Enregistre les modifications de l’index
  • Message obligatoirement associé au commit + Auteur, date, etc.
  • Éventuellement un tag

Commit ⛳️

En principe : - Opération atomique, le projet fonctionne avant et après - Pas trop gros ni trop petit - Contribution unique : Pas 3 corrections de bugs et 2 nouvelles fonctionnalités dans le même commit !! Permet de trouver un bug par recherche dichotomique (git bisect) - Représente la majeure partie de git (utilisation sous-jacente dans les stashes et autres)

Commit, commande

    git commit -m "added a wonderful new feature"

ou si on veut ajouter en même temps les modifications portant sur des fichiers existants :

    git commit -am "added a wonderful new feature"

Log

Liste des commits détaillée jusqu’à HEAD par défaut (pointeur vers le commit actuel)

  • Plus concise avec --oneline
  • Juste les n derniers avec -n
  • Entre 2 commits définis par hash, tag, branche ou autre (ex : git log master branch1)
  • avec ^ : un commit en arrière en unaire (^^^ : 3 commits en arrière)
  • avec ~n : n commits en arrière (ex HEAD~3)

Premier travail

  • Créer un petit projet demo
  • Y ajouter un Readme.md
  • Commiter
  • Changer quelque chose au Readme.md
  • Utiliser git diff pour afficher les différences
  • Commiter la nouvelle version
  • N'oubliez pas d'utiliser git status, git log, etc.

Branches

Branches 🌵

Pour séparer le développement : - Nouvelle fonctionnalité - Correction de bugs, etc.

Master/Main (ou Trunk en SVN) 🌳

  • Version principale
  • À partir d’elle, on peut créer des branches
  • Créée par défaut à l’initialisation (master en local, main sur github, gitlab, etc.)

Destin d’une branche

Une branche peut : - Être à nouveau fusionnée (merged) dans le master - Disparaître - Donner lieu à un nouveau programme, un fork

Créer et utiliser une branche

  git branch db-integration
  git checkout db-integration

en une ligne :

  git checkout -b db-integration

Crée une branche et bascule HEAD vers celle-ci

Merge

  • Fusion de branches entre elles
  • En général, d’une branche dans le master/main
  • Depuis la branche main, fusion de db-integration :
  git merge db-integration

Schéma

Commits, branches et merge git commits et branches

Conflits 🤼‍♂️

  • Certaines modifications peuvent être contradictoires
  • Par exemple, lorsque deux personnes ont apporté des modifications différentes à la même partie d’un fichier…
  • Il faut alors résoudre ce conflit !
  • Possibilité d’annuler avec git merge --abort

mergetools

  • vscode
  • atom
  • vim
  • kdiff3
  • opendiff
  • meld

Git dans tous ses états

Etats Git

Dépôt distant

Étape préliminaire : credentials ou clef ssh

Pour éviter de retaper les identifiants/MdP :

  # conserve les identifiants pendant 1h
  git config --global credential.helper 'cache --timeout=3600' 

Pour github, nécessité de créer une clef ssh

Clef ssh, création

Créer la clef :

  # algorithme choisi avec l'option -t
  ssh-keygen -t ed25519 -C "adresse@univ-orleans.fr" 
  • Nom par défaut : id_{algorithme}
  • Possibilité de donner ou non une phrase de passe pour débloquer la clef
  • Génère une paire de clefs privée/publique dans le dossier .ssh , e.g. id_ed25519/id_ed25519.pub

Clef ssh, upload sur github (ou gitlab)

  • Copier le contenu de la clef publique (id_{algo}.pub)

  • Sur github : Settings -> SSH and GPG keys -> New SSH key

  • Coller le contenu dans le champ Key puis confirmer

  • Sur gitlab : Preferences (en cliquant sur la photo de profil en haut à droite) -> SSH keys à gauche -> …

“Débloquer” la clef

  • Garder la clef en mémoire dans le terminal :

      # Créé une nouvelle instance ssh et ajoute la clef
      eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519
  • Besoin d’entrer la phrase de passe 1 seule fois

Configurer un dépôt distant

  • Une fois que vous avez un contenu versionné localement
  • Créez un dépôt distant, par exemple : https://gitlab.com/bob/demo.git
  • Pour ajouter le dépôt distant :
  git remote add origin https://gitlab.com/bob/demo.git

Ou, à partir d’un dépôt distant préexistant :

  git clone https://gitlab.com/bob/demo.git

Ajoute par défaut le remote (+branche en upstream)

Ajouter d’autres remotes

Si vous voulez travailler avec Alice:

  git remote add alice https://gitlab.com/alice/monproject.git

Lister vos remotes:

  git remote -v

Mise à jour (pull) 🆕

  • Consiste en deux commandes, fetch et merge de la branche distante
  • Synchronise la copie de travail locale avec le dépôt distant (fetch)
  • Intègre la dernière version des fichiers du dépôt distant (merge)
  • C’est à cette occasion que des conflits de version peuvent apparaître :)
    git pull [-u] origin master 

Publiez votre travail (push)

    # -u :set upstream, met à jour les arguments par défaut (branche et dépôt distant)
    git push [-u] origin master 

et quand vous aurez du nouveau contenu à mettre à jour :

    git push

git avec dépôt distant

git distant

Revenir en arrière

Reset

Permet de déplacer le curseur HEAD sur le commit donné, plusieurs options : - --soft, aucune modification sur le système de fichier, index conservé (état avant commit -m) ; - --mixed (défaut), idem mais index non conservé (aucun git add fait) ; - --hard, revient au commit en modifiant aussi les fichiers.

Checkout

Si utilisé avec un hash de commit (ou branche ou autre), détache HEAD pour se placer sur le commit.

Possibilité de revenir avec git switch - (sans argument)

Reflog

Historique de HEAD, pour revenir à un commit si problème avec reset, HEAD@{n}désignant la n-ième position de HEAD avant l’actuelle.

git reset HEAD@{1} pour revenir à la position précédente.

Réécrire l’histoire

Correction de dernière minute

Modifier le dernier commit avec git commit --amend (après avoir fait les modifications avec git add etc.).

Le commit sera forcément différent : changement de date -> changement de hash

À ne pas faire si le commit a déjà été envoyé sur le dépôt distant.

rebase

Alternative au merge : on réécrit une branche par rapport à celle sur laquelle on se cale

Rebaser la branche feature sur main (branche feature active) :

  git rebase [-i] main

Rebase normal : applique bêtement les commits de main avant les commits de feature

Avec -i : interactif, demande une action pour chaque commit

Contribuer à un projet opensource

  1. Choisir un projet sympa (nodejs, ruby on rails, d3js, etc.) sur github ou gitlab
  2. Forkez-le sur Github ou Gitlab
  3. clonez votre fork localement
  4. choisissez un bug signalé ou une nouvelle fonctionnalité demandée Par exemple NodeJS Github repo

Contribuez

  1. Créez une branche pour développer le code correspondant
  2. Publiez cette branche sur votre dépôt
  3. Soumettez un Pull Request ou PR (Github) Soumettez un Merge Request ou MR (Gitlab)
  4. Attendez le verdict. Si refus, retour à 5

Motifs de refus 😭

  • Merge impossible (rebasage nécessaire …)
  • Style non conforme, manque de commentaires/doc
  • Manque de tests ou tests qui échouent
  • Fonctionnalité non désirée (ajoute de la maintenance, etc.)

Integration continue

  • certains tests ou programmes peuvent être automatiquement lancés quand certains fichiers sont mis à jour sur le dépôt
  • spécifié dans un fichier .gitlab-ci.yml sur Gitlab
  • similaire à un Dockerfile

TDD - méthodes agiles

  • Test-Driven Development
  • Kent Beck 2003
  • premiers concepts d'extreme programming
  • méthodes agiles

Agile

  • Les méthodes agiles constituent de nouveaux modes d’organisation
  • Pas seulement en informatique
  • Industrie automobile, logistique, etc.

Méthodes les plus connues

  • Pair Programming
  • Test Driven Development
  • Scrum
    • Scrum Master
    • Product Owner
    • Sprints
    • StandUp meetings
    • Retrospectives

Standup Meetings

IT daily standup meetingAn other standup meeting

But de ces meetings

  • Fournir un feedback (retrospective)
  • Organiser les étapes suivantes
  • Etre dans une position “active”

Backlogs (Todo lists)

Joli backlog

Overloaded backlog

backlog un peu chargé

Méthode Scrum

Eléments Scrum

Scrum

  • Pierre angulaire :
    • items de Backlog
    • Tests
    • TDD et versionnage
  • Groupes :
    • Typiquement 4-5 personnes
    • certains projets concernent des centaines de personnes (noyau linux, OS, etc.)

Avant tout: les Tests

  • Différentes sortes de tests
  • exemples
  • Pourquoi le TDD ?

Différentes sortes de tests

En informatique, un test est une procédure de vérification partielle d'un système

Il y a une grande diversité de tests, concentrons nous sur les 3 principales catégories

Les 3 principaux types de tests

  • tests unitaires : s’appliquent à une méthode ou fonction isolée du reste du système (d’où le nom d’unitaire)
  • tests d’intégration : comme les tests unitaires, mais sans êtres séparés du reste du système.
  • tests fonctionnels : On teste une fonctionnalité complète en décrivant une sucession d’actions effectuée par un utilisateur de l’application.

exemples

  • Pour tester une fonction, on fournit une liste d’entrées/sorties
  • Pour tester une fonctionalité, on peut décrire son comportement attendu en écrivant une User Story comme: “Alice se rend sur la page d’accueil du site, voit 2 zones de saisie de nombres qu’elle complète, puis clique sur le bouton ajouter, et constate avec plaisir que le résultat de l’addition des 2 nombres s’affiche dans une zone encadrée de vert au milieu de la page”
  • Voir TDD with Python

Test-Driven Development

  • si on formalise l’idée de penser d’abord en termes d’exemples d’entrées/sorties examples avant de coder
  • on arrive naturellement au TDD :
    • definir les tests
    • puis on code

Automatiser les tests

Tous les langages ont leur librairie de tests unitaires

  • phpUnit en PHP
  • JUnit en Java
  • pytest ou unnitest en Python
  • GoogleTest ou Boost en C++

2021 Gérard Rozsavolgyi & Florian Groult roza @ univ-orleans.fr / florian.groult @ univ-orleans.fr