Git: un élément essentiel au quotidien

Download nbviewer Onyxia
Binder Open In Colab githubdev

Pourquoi faire du Git ?

Dans un projet, il est commun de se demander (ou de demander à quelqu’un) :

  • quelle était la bonne version d’un programme
  • qui était l’auteur d’un bout de code en particulier
  • si un changement était important ou juste un essai
  • où retrouver des traces d’un vieil essai abandonné mais potentiellement finalement prometteur
  • comment fusionner des programmes écrits par plusieurs personnes
  • etc.

Il existe un outil informatique puissant qui répond à tous ces besoins : la gestion de version (version control system (VCS) en anglais). Ses avantages sont incontestables et permettent de facilement :

  • enregistrer l’historique des modifications d’un ensemble de fichiers
  • revenir à des versions précédentes d’un ou plusieurs fichiers
  • rechercher les modifications qui ont pu créer des erreurs
  • partager ses modifications et récupérer celles des autres
  • proposer des modifications, les discuter, sans pour autant modifier d’emblée la dernière version existante
  • identifier les auteurs et la date des modifications

En outre, ces outils fonctionnent avec tous les langages informatiques (texte, R, Python, SAS, $\LaTeX$, Java, etc.) car reposent sur la comparaison des lignes et des caractères des programmes.

On peut ainsi résumer les principaux avantages du contrôle de version de la manière suivante :

  1. Conserver et archiver l’ensemble des versions d’un code ou d’une documentation
  2. Travailler efficacement en équipe
  3. Améliorer la qualité des codes
  4. Simplifier la communication autour d’un projet

Conserver et archiver du code

Une des principales fonctionnalités de la gestion de version est de conserver l’ensemble des fichiers de façon sécurisée et de proposer un archivage structuré des codes. Les fichiers sont stockés dans un dépôt, qui constitue le projet.

Tout repose dans la gestion et la présentation de l’historique des modifications. Chaque modification (ajout, suppression ou changement) sur un ou plusieurs fichiers est identifiée par son auteur, sa date et un bref descriptif1. Chaque changement est donc unique et aisément identifiable quand les modifications sont classées par ordre chronologique. Les groupes de modifications transmis au dépôt sont appelées commit.

Avec des outils graphiques, on peut vérifier l' ensemble des évolutions d’un fichier (history), ou l’histoire d’un dépôt. On peut aussi se concentrer sur une modification particulière d’un fichier ou vérifier, pour un fichier, la modification qui a entraîné l’apparition de telle ou telle ligne (blame)

Sur son poste de travail, les dizaines (voire centaines) de programmes organisés à la main n’existent plus. Tout est regroupé dans un seul dossier, rassemblant les éléments du dépôt. Au sein du dépôt, tout l’historique est stocké et accessible rapidement. Si on souhaite travailler sur la dernière version des programmes (ou sur une ancienne version spécifique), il n’y a plus besoin de conserver les autres fichiers car ils sont dans l’historique du projet. Il est alors possible de choisir sur quelle version on veut travailler (la dernière commune à tout le monde, la sienne en train d’être développée, celle de l’année dernière, etc.).

Travailler efficacement en équipe

Le deuxième avantage de la gestion de version représente une amélioration notable du travail en équipe sur des codes en commun.

La gestion de version permet de collaborer simplement et avec méthode. De façon organisée, elle permet de:

  • travailler en parallèle et fusionner facilement du code
  • partager une documentation des programmes grâce :
    • aux commentaires des modifications
    • à la possibilité d’une documentation commune et collaborative
  • trouver rapidement des erreurs et en diffuser rapidement la correction

A ces avantages s’ajoutent les fonctionalités collaboratives des sites de dépôt (les principaux étant Github et Gitlab), qui permettent d’intéragir via des issues, faire des suggestions de modifications, etc.

L’usage individuel, c’est-à-dire seul sur son projet, permet aussi de “travailler en équipe avec soi-même” car il permet de retrouver des mois plus tard le contenu et le contexte des modifications. Cela est notamment précieux lors des changements de poste ou des travaux réguliers mais espacés dans le temps (par exemple, un mois par an chaque année). Même lorsqu’on travaille tout seul, on collabore avec un moi futur qui peut ne plus se souvenir de la modification des fichiers.

Améliorer la qualité des codes

Le fonctionnement de la gestion de version, reposant sur l’archivage structuré des modifications et les commentaires les accompagnant, renforce la qualité des programmes informatiques. Ils sont plus documentés, plus riches et mieux structurés. C’est pour cette raison que le contrôle de version ne doit pas être considéré comme un outil réservé à des développeurs : toute personne travaillant sur des programmes informatiques, gagne à utiliser du contrôle de version.

Les services d’intégration continue permettent de faire des tests automatiques de programmes informatiques, notamment de packages, qui renforcent la replicabilité des programmes. Mettre en place des méthodes de travail fondées sur l’intégration continue rend les programmes plus robustes en forçant ceux-ci à tourner sur des machines autres que celles du développeur du code.

Simplifier la communication autour d’un projet

Les sites de dépôts Github et Gitlab permettent de faire beaucoup plus que seulement archiver des codes. Les fonctionalités de déploiement en continu permettent ainsi de :

  • créer des sites web pour valoriser des projets (par exemple les sites readthedocs en python)
  • déployer de la documentation en continu
  • rendre visible la qualité d’un projet avec des services de code coverage, de tests automatiques ou d’environnements intégrés de travail (binder, etc.) qu’on rend généralement visible au moyen de badges (exemple ici )

Comment faire du contrôle de version ?

Il existe plusieurs manières d’utiliser le contrôle de version :

Git a été conçu, initialement pour la ligne de commande. Il existe néanmoins des interfaces graphiques performantes et pratiques, notamment lorsqu’on désire comparer deux versions d’un même fichier côte à côte. Ces interfaces graphiques couvrent la majorité des besoins quotidiens. Néanmoins, pour certaines tâches, il faut nécessairement passer par la ligne de commande.

En résumé,

Avant Gestion de version
Archivage à la main automatique
Envoi de modification mail, dossier partagé code partagé
Fusion de code copié-collé simple, sûr
Versions du modèle dossiers archivés historique riche
Gestion des erreurs à la main méthodique

Quelques bases sur Git

Copies de travail et dépôt collectif

Git est un système décentralisé et asynchrone de gestion de version. Cela signifie que:

  • Chaque membre d’un projet travail sur une copie locale du dépôt (système decentralisé). Cette copie de travail s’appelle un clone. Cela signifie qu’on n’a pas une cohérence en continue de notre version de travail avec le dépôt ; on peut très bien ne jamais vouloir les mettre en cohérence (par exemple, si on teste une piste qui s’avère infructueuse) ;
  • C’est lorsqu’on propose la publication de modifications sur le dépôt collectif qu’on doit s’assurer de la cohérence avec la version disponible en ligne (système asynchrone).

Le dépôt distant est généralement stocké sur une forge logicielle (Github ou Gitlab) et sert à centraliser la version collective d’un projet. Les copies locales sont des copies de travail qu’on utilise pour faire évoluer un projet:

Il est tout à fait possible de faire du contrôle de version sans mettre en place de dépôt distant. Cependant,

  • c’est dangereux puisque le dépôt distant fait office de sauvegarde d’un projet. Sans dépôt distant, on peut tout perdre en cas de problème sur la copie locale de travail ;
  • c’est désirer être moins efficace car, comme nous allons le montrer, les fonctionalités des plateformes Github et Gitlab sont également très bénéfiques lorsqu’on travaille tout seul.

Principe

Les trois manipulations les plus courantes sont les suivantes et représentées sur le diagramme ci-après :

  • commit : je valide les modifications que j’ai faites en local avec un message qui les expliquent
  • pull : je récupère la dernière version des codes du dépôt distant
  • push : je transmets mes modifications validées au dépôt distant

Les deux dernières manipulations correspondent aux interactions (notamment la mise en cohérence) avec le dépôt commun alors que la première manipulation commit correspond à la modification des fichiers faite pour faire évoluer un projet.

De manière plus précise, il y a trois étapes avant d’envoyer les modifications validées (commit) au dépôt. Elles se définissent en fonction des commandes qui permet de les appliquer quand Git est utilisé en ligne de commandes :

  • diff : inspection des modifications. Cela permet de comparer les fichiers modifiés et de distinguer les fichiers ajoutés ou supprimés
  • staging area : sélection des modifications.
  • commit : validation des modifications sélectionnées (avec commentaire).

Lors des étapes de push et pull, des conflits peuvent apparaître, par exemple lorsque deux personnes ont modifié le même programme simultanément. Le terme conflit peut faire peur mais en fait c’est l’un des apports principaux de Git que de faciliter énormément la gestion de versions différentes. Les exercices du chapitre suivant l’illustreront.

Les branches

C’est une des fonctionnalités les plus pratiques de la gestion de version. La création de branches dans un projet (qui devient ainsi un arbre) permet de développer en parallèle des correctifs ou une nouvelle fonctionnalité sans modifier le dépôt commun.

Cela permet de séparer le nouveau développement et de faire cohabiter plusieurs versions, pouvant évoluer séparément ou pouvant être facilement rassemblées. Git est optimisé pour le travail sur les branches.

Dans un projet collaboratif, une branche dite master joue le rôle du tronc. C’est autour d’elle que vont pousser ou se greffer les branches. L’un des avantages de Git est qu’on peut toujours revenir en arrière. Ce filet de sécurité permet d’oser des expérimentations, y compris au sein d’une branche. Il faut être prêt à aller dans la ligne de commande pour cela mais c’est extrêmement confortable.

Hint

Comment nommer les branches ? Là encore, il y a énormément de conventions différentes. Une fréquemment observée est :

  • pour les nouvelles fonctionnalités : feature/nouvelle-fonctionnalitenouvelle-fontionnalite est un nom court résumant la fonctionnalité
  • pour les corrections de bug : issue-numnum est le numéro de l’issue

N’hésitez pas à aller encore plus loin dans la normalisation !

Conseil de praticien: ne pas négliger le .gitignore

Un fichier à ne pas négliger est le .gitignore. Il s’agit d’un garde-fou car tous fichiers (notamment des données, potentiellement volumineuses ou confidentielles) n’ont pas vocation à être partagés.

Le site gitignore.io est très pratique. Le fichier suivant est par exemple proposé pour les utilisateurs de Python, auquel on peut ajouter quelques lignes adaptées aux utilisateurs de données:

*.html
*.pdf
*.csv
*.tsv
*.json
*.xml
*.shp
*.xls
*.xlsx

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

  1. Plus précisément, chaque modification est identifiée de manière unique par un code SHA auquel est associé l’auteur, l’horodatage et des métadonnées (par exemple le message descriptif associé). ↩︎

Next