Cette page reprend des éléments présents dans un cours dédié fait avec Romain Avouac.
Pourquoi faire du Git
?
Les problèmes classiques
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.
La solution: le contrôle de version
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
, Markdown
, LaTeX
, Java
, etc.)
car reposent sur la comparaison des lignes et des caractères des programmes.
Avantages du contrôle de version
On peut ainsi résumer les principaux avantages du contrôle de version de la manière suivante :
- Conserver et archiver l’ensemble des versions d’un code ou d’une documentation
- Travailler efficacement en équipe
- Améliorer la qualité des codes
- 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 forges
qui sont des plateformes où peuvent être stockés des dépôts.
Néanmoins, ces forges proposent aujourd’hui beaucoup de fonctionalités
qui vont au-delà de l’archivage de code :
interagir via
des issues,
faire des suggestions de modifications, exécuter du code dans des
environnements normalisés, etc.
Il faut vraiment les voir comme des réseaux sociaux du code.
Les principales plateformes dans ce domaine étant Github
et Gitlab
.
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 réplicabilité 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
enpython
) - 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)
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 travaille 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 continu 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
etGitlab
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 expliquepull
: je récupère la dernière version des codes du dépôt distantpush
: 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 permettent de les appliquer quand Git est utilisé en lignes 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.
Note
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-fonctionnalite
oùnouvelle-fontionnalite
est un nom court résumant la fonctionnalité - pour les corrections de bug :
issue-num
oùnum
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 les 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 :
Exemple de .gitignore
pour les utilisateurs de données
.gitignore
pour les utilisateurs de données
"""~~~raw
*.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-eggs/
develop/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels-wheel-metadata/
pip/python-wheels/
share*.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
-log.txt
pip-delete-this-directory.txt
pip
# 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-journal
db.sqlite3
# Flask stuff:
/
instance-cache
.webassets
# Scrapy stuff:
.scrapy
# Sphinx documentation
/_build/
docs
# PyBuilder
/
target
# Jupyter Notebook
.ipynb_checkpoints
# IPython
/
profile_default
ipython_config.py
# pyenv
-version
.python
# 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
-schedule
celerybeat
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~~~
"""
)
Footnotes
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é).↩︎
Citation
@book{galiana2023,
author = {Galiana, Lino},
title = {Python Pour La Data Science},
date = {2023},
url = {https://pythonds.linogaliana.fr/},
doi = {10.5281/zenodo.8229676},
langid = {en}
}
Comment faire du contrôle de version ?
Il existe plusieurs manières d’utiliser le contrôle de version :
Git
. RStudio pourR
, PyCharm, Jupyter ou encore Visual Studio Code pourPython
qui peut être couplé avec diverses extensions utiles (git-graph, GitLens, etc.).Git
a initialement été conçu pour la ligne de commande. Il existe néanmoins des interfaces graphiques performantes et pratiques, notamment lorsque l’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é,