Fondamentaux du contrôle de version¶
Pourquoi un service SCM¶
Un service SCM (Source Code Management) répond a trois besoins fondamentaux d'une DSI :
- Versionner — conserver l'historique complet de chaque modification du code source
- Collaborer — permettre a plusieurs équipes de travailler en parallele sur le même codebase
- Intégrer — déclencher automatiquement les pipelines de build, test et déploiement
Sans service SCM centralise, chaque équipe utilise ses propres outils, ce qui fragmente la gouvernance, complique les audits et multiplie les risques de perte de code.
Centralise vs distribue¶
Systèmes centralises (SVN, TFVC)¶
Un serveur unique detient l'historique complet. Les développeurs effectuent un checkout d'une revision, modifient les fichiers, puis commitent vers le serveur.
graph LR
A["Developpeur A"] -->|checkout| SC1["Serveur central"]
SC1 -->|commit| SC2["Serveur central"]
B["Developpeur B"] -->|checkout| SC1
SC1 -->|commit| SC2 Limites : un seul point de défaillance, travail hors-ligne impossible, branches lourdes a gérer.
Systèmes distribues (Git, Mercurial)¶
Chaque développeur possède une copie complète du dépôt (clone). Les commits sont locaux ; la synchronisation se fait par push/pull vers un dépôt distant (remote).
graph LR
A["Developpeur A"] -->|clone| LA["depot local A"]
LA -->|push| Origin["Depot distant (origin)"]
B["Developpeur B"] -->|clone| LB["depot local B"]
Origin -->|pull| LB Avantages : travail hors-ligne, branches légères, historique complet sur chaque poste, performance.
Git : fonctionnement interne¶
Les objets Git¶
Git stocke quatre types d'objets dans .git/objects, chacun identifie par un hash SHA-1 :
| Objet | Contenu |
|---|---|
blob | Contenu d'un fichier (sans nom ni chemin) |
tree | Liste de blobs et sous-trees (répertoire) |
commit | Pointeur vers un tree, auteur, message, parent(s) |
tag | Pointeur annote vers un commit |
Le DAG (Directed Acyclic Graph)¶
Les commits forment un graphe oriente acyclique. Chaque commit pointe vers un ou plusieurs parents :
gitGraph
commit id: "A"
commit id: "B"
branch feature
commit id: "E"
commit id: "F"
checkout main
commit id: "C"
merge feature id: "D" Le commit D est un merge : il a deux parents (C et F).
Les références¶
Les branches et tags sont des pointeurs vers des commits :
graph LR
HEAD -->|pointe vers| main["refs/heads/main"]
main -->|pointe vers| D["Commit D"]
feature["refs/heads/feature"] -->|pointe vers| F["Commit F"]
tag["refs/tags/v1.0.0"] -->|pointe vers| C["Commit C"] HEAD pointe vers la branche courante. Un git checkout deplace HEAD.
Hebergement de dépôts¶
Dépôt bare¶
Un dépôt bare (git init --bare) ne contient pas de working directory, uniquement les objets Git et les références. C'est le format standard pour les dépôts distants.
Hooks serveur¶
Les hooks côté serveur s'exécutent lors d'événements Git :
| Hook | Déclencheur | Usage |
|---|---|---|
pre-receive | Avant acceptation du push | Validation de politique (branches, commits) |
update | Par branche poussee | Vérification de permissions par branche |
post-receive | Apres acceptation | Notification, declenchement CI/CD |
Git LFS (Large File Storage)¶
Git LFS remplace les fichiers volumineux (binaires, assets) par des pointeurs dans le dépôt Git. Les fichiers sont stockes sur un serveur LFS separe.
Quand utiliser LFS
Utilisez LFS pour tout fichier binaire depassant 1 Mo : images, archives, modèles ML, assets de documentation. Cela garde le dépôt Git rapide au clone et au fetch.
Modèles d'accès¶
Par dépôt¶
Chaque dépôt a sa propre liste de collaborateurs avec des rôles (owner, write, read). Simple pour les petites équipes.
Par organisation¶
Les utilisateurs sont regroupes en équipes au sein d'une organisation. Les permissions sont attribuees par équipe sur un ensemble de dépôts. Adapte aux structures de DSI.
Fork-based¶
Les contributeurs forkent le dépôt, travaillent sur leur copie, puis soumettent une pull request vers le dépôt upstream. Modèle standard de l'open source.
| Modèle | Cas d'usage | Contrôle d'accès |
|---|---|---|
| Par dépôt | Petites équipes, PoC | Fin, par dépôt |
| Organisation | DSI, équipes multiples | Par équipe/rôle |
| Fork-based | Open source, contributions | Ouvert en lecture |
Workflows de revue de code¶
Pull Request / Merge Request¶
Le développeur pousse une branche, ouvre une PR/MR, un ou plusieurs relecteurs approuvent, puis la branche est mergee.
graph LR
FB["feature-branch"] --> PR["Pull Request"] --> Revue --> Approbation --> Merge Éléments cles :
- Description du changement et lien vers le ticket
- Revue par au moins un pair (pair programming asynchrone)
- Tests automatises (CI) passes avant merge
- Protection de la branche cible (pas de push direct)
Stratégies de branches¶
Trunk-based development¶
Tout le monde commite sur main (ou via des branches de courte duree). Les releases sont coupees depuis main.
gitGraph
commit id: "A"
commit id: "B"
commit id: "C" tag: "v1.0"
commit id: "D"
commit id: "E"
commit id: "F" tag: "v1.1" Avantage : integration continue reelle. Prerequis : bonne couverture de tests, feature flags.
GitHub Flow¶
Une branche main toujours deployable. Chaque fonctionnalité est developpee sur une branche, mergee via PR.
gitGraph
commit id: "A"
commit id: "B"
branch feature
commit id: "C"
checkout main
merge feature id: "D"
commit id: "E" Avantage : simple, adapte au déploiement continu.
GitFlow¶
Branches main, develop, feature/*, release/*, hotfix/*. Modèle structure pour les releases planifiees.
gitGraph
commit id: "A"
branch develop
commit id: "B"
branch feature
commit id: "E"
commit id: "F"
checkout develop
commit id: "C"
commit id: "D"
merge feature
checkout main
merge develop id: "M"
branch hotfix
commit id: "fix"
checkout main
merge hotfix id: "H" Avantage : contrôle fin des releases. Inconvénient : complexité, merges fréquents.
Quelle stratégie choisir ?
Pour une DSI orientee développement avec déploiement continu, privilegiez GitHub Flow. Reservez GitFlow aux projets avec des cycles de release longs (logiciels embarqués, applications certifiees).
Webhooks et integrations¶
Les webhooks permettent au service SCM de notifier les systèmes externes lors d'événements :
| Événement | Déclencheur | Integration typique |
|---|---|---|
push | Nouveau commit pousse | Declenchement pipeline CI/CD |
pull_request | PR ouverte/mergee/fermee | Notification Slack, revue |
release | Nouvelle release publiee | Déploiement automatique |
repository | Dépôt cree/supprime | Inventaire automatique |
{
"type": "gitea",
"config": {
"url": "https://ci.example.com/api/v1/webhook",
"content_type": "json",
"secret": "webhook-secret-token"
},
"events": ["push", "pull_request"],
"active": true
}
Vocabulaire cle¶
| Terme | Définition |
|---|---|
| Clone | Copie complète d'un dépôt distant vers un dépôt local |
| Commit | Instantane de l'état du dépôt a un moment donne |
| Branch | Pointeur mobile vers un commit |
| Tag | Pointeur fixe vers un commit (souvent une release) |
| Remote | Dépôt distant (origin, upstream) |
| Merge | Fusion de deux branches |
| Rebase | Rejoue les commits d'une branche sur une autre base |
| Pull Request | Demande de fusion avec revue de code |
| Fork | Copie d'un dépôt dans un autre namespace |
| Hook | Script execute automatiquement lors d'un événement Git |