Aller au contenu

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 :

  1. Versionner — conserver l'historique complet de chaque modification du code source
  2. Collaborer — permettre a plusieurs équipes de travailler en parallele sur le même codebase
  3. 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.

# Creer un depot bare
git init --bare /srv/git/mon-projet.git

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.

# Installer et configurer LFS
git lfs install
git lfs track "*.psd"
git lfs track "*.zip"

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