Leçon 2 sur 8
Unité · Le projet sur le disque
Git n'oublie pas, ce qui en est l'intérêt et le danger
Un dépôt se souvient de chaque version de chaque fichier qu'il a jamais contenu, ce qui est exactement ce qu'on veut pour du code et exactement ce qu'on ne peut pas permettre pour une liste de bénéficiaires. Supprimer le fichier dans un commit ultérieur ne le retire pas.
Le commit qu’on ne peut pas reprendre
git add data/raw/beneficiaries.csv
git commit -m "add survey data"
# ... realised three days later ...
git rm data/raw/beneficiaries.csv
git commit -m "remove data"
Le fichier est toujours dans le dépôt. Il est dans l’historique, dans chaque clone, sur le dépôt distant, et dans la copie locale de tous ceux qui ont tiré. Le second commit l’a retiré de l’état courant et de rien d’autre.
Sur un dépôt contenant des données de protection ou de santé, c’est une divulgation. Non une erreur à corriger plus tard — une divulgation, avec les mêmes obligations que n’importe quelle autre.
D’où une règle préventive plutôt que corrective. On ne peut pas dé-commiter des données personnelles ; on ne peut que les empêcher d’entrer.
Le .gitignore qu’on écrit avant le premier commit
# Raw data. Nothing under here is ever committed.
data/raw/*
!data/raw/.gitkeep
!data/raw/CHECKSUMS
# Derived data, regenerated by the pipeline
outputs/
# Credentials, in every form they arrive in
.env
*.pem
*_secret*
config.local.*
# Editor and language noise
.Rhistory
.RData
__pycache__/
*.pyc
.DS_Store
.ipynb_checkpoints/
Écrivez-le en premier, commitez-le en premier. Un .gitignore ajouté après le
premier commit est un .gitignore arrivé trop tard pour la chose qu’il devait
attraper.
Les négations comptent. data/raw/* exclut tout, puis !data/raw/CHECKSUMS
laisse revenir exactement le fichier qui prouve quel export a servi — la provenance
sans le contenu.
Ce que « données personnelles » signifie ici, précisément
C’est plus large qu’une colonne de noms, et les jeux de données de ce secteur le démontrent.
| Paraît anonyme | Ne l’est pas, parce que |
|---|---|
| Un identifiant de cas | Il se joint à un système de gestion de cas qui a le nom |
| Les coordonnées GPS d’un ménage | C’est une adresse |
| Date de naissance plus commune plus sexe | Trois champs identifient la plupart des gens dans une petite commune |
| La photographie d’un formulaire | Chaque champ qui y figure |
| Une colonne de notes en texte libre | Elle contient ce que le travailleur social a tapé |
Le cours de protection a établi l’arithmétique : une ventilation à quatre entrées d’un jeu de données anonyme a produit dix-neuf cellules de un, et une cellule de un est une identification.
Le test n’est donc pas « y a-t-il une colonne de noms ». C’est de savoir si une combinaison quelconque de ce que contient le fichier pourrait désigner une personne — et dans une petite commune, elle le peut généralement.
La vérification qui s’exécute avant le commit
# .git/hooks/pre-commit — or the pre-commit framework, or a CI step
if git diff --cached --name-only | grep -qE '^data/raw/'; then
echo "Refusing to commit anything under data/raw/" >&2
exit 1
fi
# The same check as an R function, run by whatever CI you have.
Un crochet qui refuse vaut mieux qu’une politique qui rappelle. Le mode d’échec est quelqu’un de pressé à 18 heures, et un rappel n’y survit pas.
Ajoutez une recherche des formes que prennent les secrets, parce qu’un jeton collé
dans un script est l’autre cas courant. gitleaks et detect-secrets le font tous
deux en une étape d’intégration continue.
Que faire si c’est déjà arrivé
L’ordre compte et la première étape n’est pas technique.
Un : signalez-le. Votre organisation a une procédure d’incident de données. C’en est un, et le caractère public ou non du dépôt décide de l’urgence, non de la nécessité.
Deux : renouvelez tout ce qui était un identifiant. Un jeton commité est compromis définitivement ; le supprimer n’y change rien.
Trois : réécrivez l’historique, avec git filter-repo ou BFG, et forcez la
poussée. Chaque clone existant doit être supprimé et recloné — un clone que personne
n’a recloné contient encore le fichier.
Quatre : supposez qu’il a été récupéré. Sur un dépôt public, supposez que le fichier a été téléchargé et copié, et traitez la divulgation comme complète.
git filter-repo --path data/raw/beneficiaries.csv --invert-paths
La troisième étape est la seule qui ressemble à une correction et c’est la moins importante.
Les commits sur un travail d’analyse
Les habitudes diffèrent de celles du développement logiciel sur deux points qu’il vaut la peine de nommer.
Commitez le code et la sortie ensemble quand la sortie est commitée. Une figure et le script qui l’a produite appartiennent au même commit, pour qu’un relecteur voie si le graphique correspond au changement.
Écrivez le pourquoi dans le message. corrige les noms de communes est ce que le
diff montre déjà. « Regrouper quatre orthographes de Nord-Ouest ; sans regroupement, le
pire district se fragmente et aucun fragment ne paraît alarmant » est ce dont un
successeur a besoin et qu’il ne peut pas retrouver.
git commit -m "Group four spellings of Nord-Ouest before computing coverage
Ungrouped, the worst district splits into fragments of 727, 33, 22 and 20
households and none of them looks alarming. The 20-household fragment shows
0% open defecation, which a district table would report as a solved problem."
Une branche par question d’analyse, non par journée. Une branche qui répond à
« la couverture diffère-t-elle par district » peut être relue et fusionnée ; une
branche appelée travail non.
Ce que devrait contenir un dépôt d’analyse de programme
project/
.gitignore committed first
README.md what it produces, how to run it, what to know
uv.lock the environment, pinned
src/ every transformation
tests/ the checks that fail loudly
data/
raw/ .gitkeep and CHECKSUMS only
reference/ committed: thresholds, admin codes, lookup tables
outputs/ ignored
Les tables de référence sont commitées et les données brutes non, et la ligne qui les sépare est de savoir si le fichier décrit des personnes. Les standards de croissance de l’OMS, les seuils IPC et les codes de découpage administratif sont de la référence ; une liste de ménages non.
Rapportez-le en entier
Data handling in this analysis
No raw data is committed. data/raw/ is excluded by .gitignore, with only a
CHECKSUMS file tracked so the exports used can be identified.
A pre-commit hook refuses any staged file under data/raw/ and a CI step
scans for credential patterns.
Reference tables (WHO growth standards, IPC thresholds, admin codes) are
committed; they describe no individual.
The repository is private and access is limited to the M&E team. Raw
exports are held in [the organisation's storage], not here.
La dernière ligne est celle qu’on oublie et celle qu’un audit demande. Dire où sont les données compte autant que dire où elles ne sont pas.
La suite
Du code en gestion de versions ne reproduit toujours pas un nombre si l’environnement diffère. La leçon suivante le fige, et trouve les quatre choses qui font différer une réexécution alors que rien dans le dépôt n’a changé.