Version : 1.1 · Date : 2026-10-22 · Domaine 2 de l'examen : Design and implement a source control strategy (10 à 15 %)
En une phrase : une bonne stratégie de contrôle de source dit comment l'équipe travaille (branches, pull requests), le garantit par des règles que personne ne contourne sans droit explicite (branch policies, branch protection rules, rulesets, permissions), et garde un dépôt rapide et sain (gros fichiers hors de Git, tags, récupération et purge des données).

Ce que l'examen demande#
Repris mot pour mot du guide d'étude AZ-400 (compétences mesurées au 27 juillet 2026) :
| # | Compétence mesurée (guide officiel, en anglais) | Section |
|---|---|---|
| 1 | Design a branch strategy, including trunk-based, feature branch, and release branch | 2 |
| 2 | Design and implement a pull request workflow by using branch policies and branch protection rules | 3 |
| 3 | Implement branch merging restrictions by using branch policies and branch protection rules | 4 |
| 4 | Design and implement a strategy for managing large files, including Git Large File Storage (LFS) and git-fat | 5 |
| 5 | Design a strategy for scaling and optimizing a Git repository, including Scalar and cross-repository sharing | 6 |
| 6 | Configure permissions in the source control repository | 7 |
| 7 | Configure tags to organize the source control repository | 8 |
| 8 | Recover specific data by using Git commands | 9 |
| 9 | Remove specific data from source control | 10 |
1. Les bases à maîtriser#
Tu connais Git au quotidien : ce chapitre se concentre sur ce que l'examen attend d'un DevOps engineer qui conçoit la stratégie pour une équipe, sur Azure Repos et sur GitHub.
| Notion | Ce qu'il faut avoir en tête pour l'examen |
|---|---|
| Branche | Un pointeur mobile vers un commit ; créer une branche ne coûte presque rien |
| Fast-forward | Le pointeur avance sans merge commit ; impossible si les branches ont divergé, donc jamais de conflit |
| Merge (no fast-forward) | Crée un merge commit à deux parents ; garde la trace exacte du merge |
| Rebase | Rejoue des commits sur une autre base ; historique linéaire, mais réécrit les commits (nouveaux SHA) |
| Tag | Un nom fixe sur un commit : lightweight (simple pointeur) ou annotated (auteur, date, message) |
| Pull request (PR) | Demande de fusion revue et contrôlée ; c'est sur la PR que s'appliquent les règles de protection |
Deux plateformes, une même logique, des noms différents :
| Azure Repos (Azure DevOps) | GitHub |
|---|---|
| Branch policies (revues, build, work items…) | Branch protection rules et rulesets |
| Permissions de dépôt et de branche (groupes Azure DevOps) | Repository roles (Read, Triage, Write, Maintain, Admin) |
| Automatically included reviewers (filtres de chemin) | CODEOWNERS + Require review from Code Owners |
| Build validation, Status checks | Required status checks |
2. Concevoir une stratégie de branches#

2.1 Les trois modèles de l'examen#
| Modèle | Principe | Quand le choisir | Point de vigilance |
|---|---|---|---|
| Trunk-based development | Tout le monde intègre souvent dans main (le tronc), avec des branches très courtes ; le travail inachevé est caché derrière des feature flags |
CI/CD mature, tests automatisés solides, déploiement continu | Exige une discipline forte et des tests rapides |
| Feature branch (GitHub Flow) | Une branche par fonctionnalité ou correctif, fusionnée par PR dans main, puis supprimée |
Le cas général ; c'est le socle recommandé par Microsoft | Les branches longues divergent : les garder courtes |
| Release branch (Release Flow) | On ajoute des branches release/… créées près de la sortie, longues, qui ne sont jamais remergées dans main |
Plusieurs versions maintenues en parallèle | Chaque release branch active est une version de plus à supporter |
La recommandation de Microsoft tient en trois règles (Adopt a Git branching strategy) :
- Feature branches pour tout nouveau développement et tout correctif ;
- fusion dans
mainuniquement par pull request ; - un
maintoujours de qualité et à jour (build propre, tests au vert).
2.2 Release Flow, le modèle de Microsoft#
Microsoft (équipe Azure DevOps) applique le Release Flow : les correctifs sont faits d'abord dans main, puis portés
vers la release branch par cherry-pick. On préfère le cherry-pick au merge pour contrôler exactement les commits portés
(un merge de la release dans main ramènerait des changements propres à la release).
gitGraph
commit id: "A"
branch feature/login
commit id: "B"
checkout main
merge feature/login id: "PR 1"
branch release/20
commit id: "stabilisation"
checkout main
commit id: "fix bug (PR 2)"
checkout release/20
cherry-pick id: "fix bug (PR 2)"
Quand une version n'est plus supportée : verrouiller sa release branch (Lock dans Azure Repos, Lock branch sur GitHub).
2.3 Nommer et organiser les branches#
Conventions suggérées par Microsoft : users/{alias}/{description}, feature/{nom}, bugfix/{description},
hotfix/{description}, release/{numéro}. Dans Azure Repos, on peut imposer des dossiers de branches (Require branch
folders) par les permissions : retirer Create branch au niveau du dépôt et l'accorder seulement sur feature/*, users/*…
Les branches en / s'affichent en arbre dans le portail.
Pourquoi pas des tags pour les releases ? Microsoft déconseille de gérer les releases uniquement par tags : un tag se pousse à part (
git push --tagsoublié), et on ne peut pas y appliquer de correctif. Les tags restent utiles pour marquer les versions livrées (voir section 8).
3. Le workflow de pull request : branch policies et branch protection rules#

3.1 Azure Repos : les branch policies#
Dès qu'une policy est active sur une branche, Azure Repos applique automatiquement deux règles : les mises à jour de la branche passent par une PR, et la branche ne peut plus être supprimée. Les policies s'appliquent selon la branche cible de la PR : ne pas en mettre sur des branches temporaires (leur suppression automatique échouerait).
| Policy | Ce qu'elle impose | Options à connaître |
|---|---|---|
| Require a minimum number of reviewers | N approbations | Allow requestors to approve their own changes ; Prohibit the most recent pusher from approving (séparation des tâches) ; Allow completion even if some reviewers vote to wait or reject ; au push : Require at least one approval on the last iteration, Reset all approval votes, Reset all code reviewer votes |
| Check for linked work items | Un work item lié (traçabilité) | Required ou Optional |
| Check for comment resolution | Tous les commentaires résolus | Required ou Optional |
| Limit merge types | Les merge types autorisés | voir section 4 |
| Build Validation | Un pipeline réussi sur le merge simulé de la PR | Trigger automatique ou manuel, expiration du résultat, filtre de chemin |
| Status Checks | Un statut réussi posté par un service externe (outil de sécurité, qualité…) | Badge External dans la PR depuis 2026 |
| Automatically included reviewers | Des relecteurs ajoutés selon les chemins modifiés | Required ou Optional, filtres /infra/*;!/infra/tests/* |
Microsoft recommande deux relecteurs pour une PR importante, et ne pas laisser l'auteur s'auto-approuver sur main.
En CLI (extension azure-devops), exemples issus de Microsoft Learn :
# 2 approbations, l'auteur ne compte pas, votes remis à zéro au push
az repos policy approver-count create \
--blocking true --enabled true --branch main --repository-id <repo-id> \
--minimum-approver-count 2 --creator-vote-counts false --reset-on-source-push true \
--allow-downvotes false
# Relecture obligatoire de l'équipe sécurité sur l'infra et les pipelines
az repos policy required-reviewer create \
--blocking true --enabled true --branch main --repository-id <repo-id> \
--message "Security review required for protected paths." \
--path-filter "/infra/*;/pipelines/*" --required-reviewer-ids <email-ou-groupe>
# Build validation : le pipeline CI doit passer sur chaque PR vers main
az repos policy build create \
--blocking true --enabled true --branch main --repository-id <repo-id> \
--build-definition-id <id-pipeline> --display-name "CI PR" \
--manual-queue-only false --queue-on-source-update-only true --valid-duration 720
# Commentaires résolus obligatoires
az repos policy comment-required create --blocking true --enabled true --branch main --repository-id <repo-id>
--branch-match-type prefix applique la policy à tout un dossier (par exemple release/).
3.2 GitHub : branch protection rules et rulesets#
Branch protection rule (une seule par branche, motif fnmatch comme release/*) :
| Réglage | Effet |
|---|---|
| Require a pull request before merging | Pas de push direct ; N required approving reviews |
| Dismiss stale pull request approvals when new commits are pushed | Les approbations tombent au nouveau push |
| Require review from Code Owners | Un propriétaire défini dans CODEOWNERS doit approuver |
| Require approval of the most recent reviewable push | Le dernier push doit être approuvé par quelqu'un d'autre que son auteur |
| Require status checks to pass | Checks obligatoires ; mode strict = la branche doit être à jour avec la base |
| Require conversation resolution | Tous les commentaires résolus |
| Require signed commits | Commits signés et vérifiés seulement |
| Require linear history | Pas de merge commit (squash ou rebase seulement) |
| Require merge queue | File d'attente qui teste chaque PR sur la dernière version de la branche |
| Require deployments to succeed | Déploiement réussi vers des environnements donnés avant merge |
| Lock branch | Branche en lecture seule |
| Do not allow bypassing the above settings | Les règles s'appliquent aussi aux admins |
| Restrict who can push / Allow force pushes / Allow deletions | Force push et suppression désactivés par défaut |
Rulesets (plans Team et Enterprise ; rulesets d'organisation multi-dépôts avec Enterprise) : une liste nommée de règles pour des branches, des tags ou des pushs. Différences clés avec les branch protection rules :
| Branch protection rule | Ruleset | |
|---|---|---|
| Combien sur une branche | Une seule | Plusieurs, cumulées ; en cas de conflit, la plus restrictive s'applique |
| Visibilité | Admins | Toute personne en lecture voit les rulesets actifs |
| Statut | Active ou supprimée | Active ou Disabled sans suppression |
| Contournement | Admins sauf Do not allow bypassing | Bypass list (rôles, équipes, GitHub Apps) |
| Portée | Branches | Branches, tags, push rulesets (chemins, extensions, taille de fichier, sur tout le réseau de forks) |
| Plus | — | Règles sur les métadonnées de commit (message, e-mail de l'auteur) |
# GitHub CLI : lister les rulesets du dépôt et voir lesquels s'appliquent à une branche
gh ruleset list
gh ruleset check main
3.3 CODEOWNERS#
Le fichier CODEOWNERS désigne les propriétaires de chemins ; ils sont demandés automatiquement en revue, et deviennent
obligatoires avec Require review from Code Owners.
# .github/CODEOWNERS : la dernière règle qui correspond l'emporte
* @fabrikam/platform
/infra/ @fabrikam/cloud-ops
/pipelines/ @fabrikam/cloud-ops @fabrikam/security
/.github/CODEOWNERS @fabrikam/security
À retenir : emplacements cherchés dans l'ordre .github/, racine, docs/ (le premier trouvé gagne) ; le fichier doit être
sur la branche de base de la PR ; les propriétaires doivent avoir un accès write explicite ; une seule approbation
d'un des propriétaires suffit ; protéger le fichier lui-même en lui donnant un propriétaire.
Équivalent Azure Repos : la policy Automatically included reviewers avec des filtres de chemin.
4. Restreindre les merges#
4.1 Les merge types d'Azure Repos#

| Merge type (Azure Repos) | Paramètre CLI | Historique obtenu |
|---|---|---|
| Basic merge (no fast-forward) | --allow-no-fast-forward |
Merge commit, historique non linéaire exact |
| Squash merge | --allow-squash |
Un seul commit sur la cible, linéaire |
| Rebase and fast-forward | --allow-rebase |
Commits rejoués, linéaire, sans merge commit |
| Rebase with merge commit (semi-linéaire) | --allow-rebase-merge |
Commits rejoués + merge commit |
# main : seulement squash (historique propre pour des branches courtes)
az repos policy merge-strategy create --blocking true --enabled true --branch main --repository-id <repo-id> \
--allow-squash true --allow-no-fast-forward false --allow-rebase false --allow-rebase-merge false
Microsoft rappelle que Limit merge types est un réglage de gouvernance de l'historique, pas un contrôle de sécurité : si l'audit exige la séquence exacte des commits, préférer le merge commit au squash. Le rebase à la complétion de la PR est impossible si la branche source a elle-même des policies.
Sur GitHub : dans les paramètres du dépôt, autoriser ou non merge commits, squash merging, rebase merging ; et Require linear history dans la règle de protection.
4.2 Empêcher les contournements#
| Mécanisme | Azure Repos | GitHub |
|---|---|---|
| Pousser directement sur la branche protégée | Refusé dès qu'une policy existe, sauf Bypass policies when pushing | Refusé avec Require a pull request, sauf bypass |
| Compléter une PR qui ne respecte pas les règles | Bypass policies when completing pull requests (case Override branch policies and enable merge) | Admins ou bypass list, sauf Do not allow bypassing |
| Réécrire l'historique, supprimer la branche | Permission Force push (non accordée par défaut) | Allow force pushes / Allow deletions (désactivés par défaut) |
| Geler la branche | Lock (le créateur du lock ou Remove others' locks déverrouille) | Lock branch |
Les deux permissions de bypass d'Azure Repos ont remplacé l'ancienne Exempt from policy enforcement. Microsoft insiste : les réserver à un très petit nombre d'administrateurs ou à une procédure d'urgence documentée.

5. Gérer les gros fichiers : Git LFS, git-fat, Azure Artifacts#

5.1 Ce qui va où#
| Type de fichier | Où le mettre |
|---|---|
| Code source, scripts, texte, JSON | Git |
| Petits binaires rarement modifiés (icônes, images web) | Git, en restant prudent : 100 modifications d'un binaire de 100 Ko pèsent autant que 10 modifications d'un binaire de 1 Mo |
| Gros binaires qui changent souvent et ne se « diffent » pas (vidéos, maquettes, modèles 3D) | Git LFS |
| Dépendances, bibliothèques, livrables versionnés | Azure Artifacts ou GitHub Packages (chapitre 03) |
| Sorties de build, logs, archives compressées | Nulle part dans Git |
Limites Azure Repos à connaître : fichier ≤ 100 Mo conseillé, dépôt < 10 Go conseillé (250 Go maximum), push ≤ 5 Go (les objets LFS ne comptent pas dans cette limite). La policy de dépôt Maximum file size bloque à la source tout push qui contient un fichier trop gros ; d'autres policies de dépôt existent (File path validation, Commit author email validation, Reserved names, Maximum path length, Case enforcement).
5.2 Git LFS#
Git LFS stocke dans le dépôt un pointeur de quelques lignes et met le contenu réel dans un stockage séparé ; le bon contenu est téléchargé au clone ou au changement de branche. Azure Repos le prend en charge gratuitement.
git lfs install # une fois par poste
git lfs track "*.psd" "*.mp4" # écrit les règles dans .gitattributes
git add .gitattributes # à committer AVANT les fichiers suivis
git add design/maquette.psd && git commit -m "add mockup"
git lfs migrate import --include="*.zip" # convertir l'historique existant (réécrit les commits)
# Pipeline Azure : télécharger les fichiers LFS au checkout
steps:
- checkout: self
lfs: true
Limites à connaître : chaque poste doit avoir le client LFS (sinon on récupère les pointeurs) ; Git ne fusionne pas deux
versions d'un binaire (coordination, file locking LFS) ; pas de SSH sur Azure Repos pour un dépôt avec LFS ; glisser
un binaire dans l'interface web commit le binaire, pas le pointeur ; agent auto-hébergé : installer git-lfs.
5.3 git-fat#
git-fat (projet open source, hors documentation Microsoft hormis le guide d'étude) suit la même idée que LFS : un
filtre Git (filter=fat dans .gitattributes) remplace les gros fichiers par un marqueur, et le contenu est synchronisé
par rsync vers un serveur que vous hébergez (fichier .gitfat). Commandes : git fat init, git fat push,
git fat pull. Il ne dépend que de Python et rsync.
| Git LFS | git-fat | |
|---|---|---|
| Stockage | Service de la plateforme (Azure Repos, GitHub) | Votre serveur rsync |
| Intégration plateforme | Native (portail, pipelines, locking) | Aucune |
| Quand | Le choix par défaut | Infrastructure de stockage existante, pas de LFS côté serveur |
6. Passer à l'échelle : Scalar, clones partiels, cross-repository sharing#
6.1 Pourquoi un dépôt devient lent#
Deux causes : un long historique et des gros binaires. S'y ajoutent les dossiers très plats (des centaines
d'entrées dans un même dossier) et les branches inutilisées (chaque clone télécharge les objets de toutes les branches
distantes). Le panneau Health and usage d'Azure Repos et les outils git-sizer ou git survey mesurent ces facteurs.
Piège : le stockage Azure Repos est append-only. Supprimer une branche ou forcer un push ne réduit pas un dépôt déjà gros ; seule la recréation du dépôt avec le contenu utile libère la place.
6.2 Scalar et les clones partiels#
Scalar (Microsoft, intégré à Git) accélère les très gros dépôts en activant des fonctions avancées de Git :
| Fonction activée par Scalar | Effet |
|---|---|
| Partial clone | Ne télécharge pas tous les objets tout de suite |
| Background prefetch | Récupère les objets des remotes toutes les heures |
| Sparse-checkout | Ne matérialise que les dossiers utiles |
| File system monitor | Évite de scanner tout le working tree |
| Commit-graph, multi-pack-index, incremental repack | Accélèrent git log et la recherche d'objets |
scalar clone https://dev.azure.com/fabrikam/Plateforme/_git/monorepo # clone optimisé
git clone --depth 1 <url> # shallow clone : historique limité (idéal en CI)
git clone --filter=blob:none <url> # partial clone : historique complet, contenus à la demande
git sparse-checkout set services/api infra # ne garder que ces dossiers
En pipeline Azure, le paramètre fetchDepth du checkout limite la profondeur de fetch. Microsoft cite aussi VFS for Git
(protocole GVFS d'Azure Repos), l'ancêtre de Scalar pour Windows et Office.
6.3 Monorepo, multirepo et partage entre dépôts#
| Monorepo | Plusieurs dépôts | |
|---|---|---|
| Avantages | Refactoring atomique, une seule version de tout, visibilité | Autonomie des équipes, permissions et pipelines par dépôt, clones légers |
| Inconvénients | Taille, pipelines à filtrer par chemin, permissions grossières | Versions à coordonner, dépendances entre dépôts |
| Outils | Scalar, sparse-checkout, filtres de chemin des policies et triggers | Packages partagés (Azure Artifacts), submodules, templates de pipeline dans un dépôt dédié |
Cross-repository sharing : partager du code commun entre dépôts par des packages versionnés (le plus robuste), des Git
submodules (fichier .gitmodules, pointeur vers un commit d'un autre dépôt) ou des outils comme git-subrepo.
7. Les permissions du dépôt#

7.1 Azure Repos#
Trois niveaux, avec héritage : Git repositories (tous les dépôts du projet) → un dépôt (héritage désactivable) → une branche (sous-ensemble des permissions).
| Permission | Effet | Par défaut |
|---|---|---|
| Read | Cloner, lire ; contribuer aux PR (commenter, voter) | Readers et plus |
| Contribute | Pousser sur les branches existantes, compléter des PR | Contributors |
| Create branch | Publier une nouvelle branche sur le serveur | Contributors |
| Create tag | Pousser des tags | Contributors |
| Manage notes | Pousser des notes Git | Contributors |
| Create / Delete / Rename repository | Gérer les dépôts | Project Administrators |
| Edit policies | Modifier les branch policies | Project Administrators |
| Manage permissions | Modifier les permissions | Project Administrators |
| Remove others' locks | Déverrouiller la branche d'un autre | Project Administrators |
| Force push (rewrite history, delete branches and tags) | Réécrire l'historique, supprimer branches et tags | Aucun groupe |
| Bypass policies when completing pull requests / when pushing | Passer outre les policies | Aucun groupe |
Le créateur d'une branche reçoit sur celle-ci Contribute, Force push, Manage permissions et Remove others' locks
(pour pouvoir supprimer sa branche après la PR). Depuis 2023, il ne reçoit plus Edit policies automatiquement. Sur une
branche commune comme main, revoir ces droits.
Modèle recommandé par Microsoft pour main : Contributors contribuent par PR sans bypass ; Project Administrators ont Edit
policies et Manage permissions ; les droits de bypass seulement pour des responsables d'urgence si la procédure l'exige.
7.2 GitHub#
| Rôle de dépôt | Pour qui |
|---|---|
| Read | Lire, ouvrir des issues et commenter (non-développeurs) |
| Triage | Gérer issues et PR sans droit d'écriture |
| Write | Pousser sur le dépôt |
| Maintain | Gérer le dépôt sans actions sensibles ou destructrices |
| Admin | Tout, y compris la sécurité et la suppression |
S'y ajoutent les base permissions de l'organisation (droit minimal de tous les membres, hors collaborateurs externes), les teams, les rôles personnalisés (Enterprise) et des rôles d'organisation comme Security manager (lecture de tous les dépôts). Un accès plus élevé sur un dépôt l'emporte sur la base permission.
8. Les tags#
| Type | Contenu | Création |
|---|---|---|
| Lightweight | Un simple pointeur vers un commit | git tag v1.4.0 |
| Annotated | Objet complet : auteur, date, message (et signature possible) | git tag -a v1.4.0 -m "Release 1.4.0" |
git tag -a v2.3.0 9fceb02 -m "Release 2.3.0" # tagger un commit précis
git push origin v2.3.0 # un tag se pousse à part !
git push origin --tags # ou tous les tags
git tag -d v2.3.0 && git push origin --delete v2.3.0 # supprimer (Force push requis sur Azure Repos)
Points d'examen :
- Azure Repos : le portail (vues Tags et Commits) ne crée que des tags annotés ; les tags lightweight se créent en ligne de commande ; il faut la permission Create tag (Contributors) ; supprimer un tag demande Force push.
- Nommage : suivre le versionnement sémantique avec un
v(v1.0.0,v0.2.0-alpha,v5.9-beta.3) ; noms en minuscules séparés par des tirets ; pas d'espaces ni de~ou:; pas de nom de 40 caractères hexadécimaux (confusion avec un SHA). - GitHub : un tag peut porter une release (notes, binaires) ; les rulesets ciblent aussi les tags (qui peut créer, supprimer, renommer).
- Garder un nombre raisonnable de tags : ils sont transférés à chaque fetch (quelques dizaines de milliers au plus).
- Versionnement des packages et artefacts : chapitre 03.
9. Récupérer des données avec Git#

Tant qu'un objet existe dans le dépôt local ou distant, on peut le retrouver.
| Besoin | Commande |
|---|---|
| Retrouver l'historique | git log, git log --all -- chemin/fichier |
| Revenir à l'état d'un commit | git checkout <commit> (HEAD détachée) |
| Restaurer un fichier d'un ancien commit | git checkout <commit> -- <fichier> ou git restore --source <commit> <fichier> |
| Restaurer un fichier supprimé | git checkout <commit_qui_le_supprime>^ -- <fichier> (le ^ vise le parent) |
| Annuler des modifications locales non commitées | git restore <fichier> |
| Afficher un fichier à une date donnée | git show <commit>:<fichier> |
| Trouver qui a changé une ligne | git blame <fichier> |
| Reprendre un commit d'une autre branche | git cherry-pick <commit> |
| Annuler un commit déjà poussé, sans réécrire | git revert <commit> |
| Retrouver un commit ou une branche « perdus » (reset, suppression) | git reflog, puis git branch recup <sha> |
| Lister les commits inaccessibles | git fsck --lost-found |
flowchart TD
A["Donnée perdue"] --> B{"Déjà poussée sur le serveur ?"}
B -- "Oui, branche supprimée sur Azure Repos" --> C["Portail : Branches, nom exact,<br/>Restore branch"]
B -- "Non, perdue en local" --> D["git reflog : retrouver le SHA"]
D --> E["git branch recup SHA"]
B -- "Un fichier seulement" --> F["git checkout SHA^ -- fichier"]
C --> G["Policies et permissions à recréer"]
Côté Azure Repos, une branche supprimée se restaure depuis le portail : vue Branches, rechercher le nom exact, lien Search for exact match in deleted branches, puis Restore branch. Il n'y a pas de rétention sur les branches supprimées, mais les policies et permissions ne sont pas restaurées. Un dépôt supprimé passe par la corbeille (recycle bin, API REST).
10. Supprimer des données du contrôle de source#
Trois raisons : réduire la taille, retirer un gros fichier ajouté par erreur, retirer un fichier sensible (mot de passe, clé).
10.1 La démarche pour un secret#
- Révoquer et renouveler le secret immédiatement : dès qu'il est poussé, il doit être considéré comme compromis ; le nettoyage de l'historique ne suffit jamais.
- Geler le dépôt (prévenir l'équipe, éventuellement Lock la branche) pour ne pas perdre de pushs pendant l'opération.
- Réécrire l'historique :
- git filter-repo : l'outil recommandé pour réécrire l'historique (remplace
git filter-branch) ; - BFG Repo-Cleaner : plus simple pour un cas courant.
- git filter-repo : l'outil recommandé pour réécrire l'historique (remplace
- Force push (permission Force push sur Azure Repos), puis chaque développeur re-clone ou rebase.
- Prévenir la récidive :
.gitignore, secret scanning push protection de GitHub Advanced Security (chapitre 07), policy Maximum file size, Key Vault pour les secrets.
# git filter-repo : retirer un fichier de tout l'historique
git filter-repo --invert-paths --path config/secrets.json
# BFG : supprimer un fichier, ou remplacer des valeurs listées dans un fichier
bfg --delete-files secrets.json
bfg --replace-text passwords.txt
git push --force --all && git push --force --tags
Si le secret est dans le dernier commit non poussé : git commit --amend. S'il est plus ancien mais non poussé : rebase
interactif (git rebase -i <commit>~1, edit, corriger, git commit --amend, git rebase --continue).
10.2 Les limites d'Azure Repos#
- Le stockage est append-only : un commit retiré de l'historique reste accessible par son SHA (et via les anciennes PR) ; l'espace n'est pas récupéré ; Azure Repos ne permet pas de supprimer un commit précis.
- La seule façon d'effacer réellement : recréer le dépôt avec le contenu nettoyé (
git push --mirrorvers un nouveau dépôt), reconfigurer policies, permissions et pipelines, puis supprimer l'ancien.
11. Labs conseillés#
Dans une organisation Azure DevOps et un compte GitHub de test (gratuits pour ces labs).
- Protéger
maindans Azure Repos- Créer un dépôt, puis ajouter en CLI : 2 relecteurs avec reset au push, build validation sur un pipeline YAML simple, commentaires résolus, merge type squash seulement.
- Pousser directement sur
main, puis ouvrir une PR. - Résultat attendu : le push direct est refusé ; la PR reste bloquée tant qu'il manque une approbation ou que le build échoue.
- Reproduire la même protection sur GitHub
- Créer un ruleset sur
main: PR obligatoire, 1 approbation, dismiss stale, linear history ; ajouter unCODEOWNERSsur/infra/et activer Require review from Code Owners. - Modifier un fichier sous
/infra/dans une PR. - Résultat attendu : le code owner est demandé automatiquement et son approbation est exigée.
- Créer un ruleset sur
- Git LFS
git lfs install,git lfs track "*.bin", committer.gitattributes, puis un fichier de 50 Mo ; cloner ailleurs avec et sans client LFS ; ajouterlfs: truedans le checkout d'un pipeline.- Résultat attendu : sans client LFS on obtient un pointeur texte ; avec, le vrai fichier ; le pipeline récupère le binaire.
- Récupération
- Supprimer une branche poussée, la restaurer depuis le portail Azure Repos ; en local,
git reset --hard HEAD~3puis retrouver les commits pargit reflog. - Résultat attendu : la branche revient sans ses policies ; les commits sont récupérés dans une nouvelle branche.
- Supprimer une branche poussée, la restaurer depuis le portail Azure Repos ; en local,
- Purge d'un faux secret
- Committer et pousser un fichier
secrets.txtcontenant une fausse valeur ; le retirer avecgit filter-repo, force push ; tenter d'ouvrir l'ancien commit par son SHA dans Azure Repos. - Résultat attendu : le fichier disparaît des branches, mais l'ancien commit reste consultable par son SHA (append-only).
- Committer et pousser un fichier
Nettoyage : supprimer les dépôts de test (corbeille Azure Repos, Delete repository sur GitHub).
12. Pièges d'examen#
| Situation dans la question | Réponse attendue | Pourquoi |
|---|---|---|
Empêcher les pushs directs sur main dans Azure Repos |
Ajouter une branch policy (n'importe laquelle) | Toute policy rend la PR obligatoire et interdit la suppression |
Imposer la revue de l'équipe sécurité sur /infra (Azure Repos) |
Automatically included reviewers avec filtre de chemin, Required | C'est l'équivalent de CODEOWNERS |
| Même besoin sur GitHub | CODEOWNERS + Require review from Code Owners | — |
| Le code doit compiler avant le merge | Build validation (Azure Repos) / Required status checks (GitHub) | Valide le merge simulé |
| Un outil externe doit valider la PR | Status check policy | Le service poste un statut |
| Une approbation doit tomber si l'auteur repousse | Reset votes / Require approval on the last iteration ; GitHub : Dismiss stale approvals | — |
| Garder un historique linéaire avec un commit par fonctionnalité | Squash merge (Limit merge types) ; GitHub : linear history + squash | — |
| L'audit exige la séquence exacte des commits | Basic merge (no fast-forward) | Le squash écrase les commits |
| Plusieurs ensembles de règles doivent s'appliquer à une même branche GitHub | Rulesets | Une seule branch protection rule par branche |
| Corriger en urgence sans attendre les policies | Bypass policies when completing pull requests, à un petit groupe | Ne pas désactiver les policies |
| Supprimer une branche ou un tag dans Azure Repos | Permission Force push | Aucun groupe ne l'a par défaut |
| Gros fichiers binaires qui changent souvent | Git LFS | Pas Artifacts (réservé aux packages) |
| Dépendances binaires (DLL, bibliothèques) | Azure Artifacts / GitHub Packages | Pas dans Git, pas dans LFS |
| Stocker les gros fichiers sur son propre serveur | git-fat (rsync) | LFS utilise le stockage de la plateforme |
| Clone très lent d'un énorme monorepo | Scalar (partial clone, sparse-checkout, prefetch) | — |
| Accélérer le checkout en CI | Shallow fetch (fetchDepth) |
— |
| Restaurer une branche supprimée sur Azure Repos | Portail, recherche du nom exact, Restore branch | Policies et permissions à recréer |
Retrouver un commit après reset --hard |
git reflog |
— |
| Secret poussé par erreur | Révoquer le secret d'abord, puis filter-repo / BFG et force push | Il est déjà compromis |
| Le dépôt Azure Repos ne rétrécit pas après la purge | Stockage append-only : recréer le dépôt | — |
| Créer un tag lightweight dans Azure Repos | Ligne de commande | Le portail ne crée que des tags annotés |
| Le tag n'apparaît pas sur le serveur | git push origin <tag> |
Les tags se poussent à part |
| LFS par SSH sur Azure Repos | Non pris en charge : HTTPS | — |
13. Scénarios corrigés#
1. Une équipe de 6 développeurs déploie en production plusieurs fois par jour avec une bonne couverture de tests. Elle veut le moins de conflits de merge possible. Quelle stratégie de branches ?
Trunk-based development : branches très courtes intégrées souvent dans
main, travail inachevé derrière des feature flags. Les release branches seraient inutiles (une seule version en production).
2. Un éditeur maintient les versions 3.x et 4.x en parallèle et doit livrer des correctifs de sécurité sur les deux. Que mettre en place ?
Des release branches (
release/3,release/4) en plus des feature branches. Corriger dansmainpuis cherry-pick vers chaque release branch (Release Flow) ; verrouiller une release branch en fin de support.
3. Sur Azure Repos, tout changement de /pipelines doit être approuvé par l'équipe plateforme, et toute PR vers main doit
avoir 2 approbations, sans que l'auteur compte. Quelles policies ?
Require a minimum number of reviewers à 2, Allow requestors to approve their own changes désactivé (
--creator-vote-counts false) ; Automatically included reviewers Required avec le filtre/pipelines/*et l'équipe plateforme.
4. Un développeur obtient l'approbation, puis pousse un nouveau commit qui modifie la logique, et complète la PR. Comment l'empêcher ?
Dans la policy de relecteurs, Reset all approval votes (ou Require at least one approval on the last iteration) quand de nouveaux changements sont poussés ; sur GitHub, Dismiss stale pull request approvals et Require approval of the most recent reviewable push.
5. L'organisation GitHub veut appliquer à tous ses dépôts la règle « pas de force push sur main » et, sur certains dépôts,
une règle plus stricte en plus. Quelle fonctionnalité ?
Des rulesets : un ruleset d'organisation (GitHub Enterprise) plus des rulesets de dépôt ; ils se cumulent, la version la plus restrictive s'applique. Une branch protection rule ne peut pas se cumuler.
6. Une équipe de jeu vidéo versionne des textures de 200 Mo modifiées chaque jour ; les clones prennent une heure. Que recommander ?
Git LFS pour ces fichiers (
git lfs track,.gitattributescommitté d'abord,git lfs migrate importpour l'historique) ; client LFS sur tous les postes etlfs: truedans les pipelines ; en HTTPS (pas de SSH avec LFS sur Azure Repos).
7. Un monorepo de plusieurs dizaines de Go : les développeurs ne travaillent que sur 2 ou 3 dossiers. Que proposer ?
Scalar (
scalar clone) qui active partial clone, sparse-checkout, background prefetch, commit-graph et file system monitor ;git sparse-checkout setpour les dossiers utiles ; shallow fetch en CI.
8. Une branche feature/paiement a été supprimée par erreur sur Azure Repos il y a 6 mois. Peut-on la récupérer ?
Oui : vue Branches, rechercher le nom exact, Search for exact match in deleted branches, puis Restore branch (pas de rétention sur les branches supprimées). Les policies et permissions de la branche sont à reconfigurer.
9. Une clé de stockage a été poussée dans main hier. Quelle est la première action ?
Révoquer / régénérer la clé du compte de stockage (et la ranger dans Key Vault). Ensuite seulement : réécrire l'historique avec git filter-repo ou BFG, force push, re-clone par l'équipe. Sur Azure Repos, l'ancien commit reste lisible par son SHA : si cela pose problème, recréer le dépôt.
10. Des Contributors ont pu supprimer des tags de release. Pourquoi, et comment l'éviter ?
Supprimer un tag demande Force push : vérifier qu'aucun Contributor n'a cette permission (accordée par exemple au créateur d'une branche, ou par une assignation directe) ; sur GitHub, un ruleset de tags qui interdit la suppression.
14. Pour aller plus loin#
- Git hooks (
pre-commit,commit-msg…) pour contrôler en local avant le push (formatage, détection de secrets) ; ils ne remplacent pas les contrôles serveur, puisque chacun peut les désactiver. - Inner source et forks : forks dans Azure Repos et GitHub pour contribuer à un dépôt sans droit d'écriture, avec PR depuis le fork.
- Commits signés (GPG, SSH ou S/MIME) et Require signed commits : prouver l'auteur réel d'un commit.
- Merge queue GitHub : teste chaque PR sur la dernière version de
mainavant de fusionner, utile quand beaucoup de PR arrivent en même temps. - Migration Azure Repos vers GitHub (Enterprise Live Migrations) : les branch policies deviennent des rulesets ; les
relecteurs par chemin doivent être recréés à la main en
CODEOWNERS. - Policies de dépôt d'Azure Repos (File path validation, Commit author email validation, Reserved names) pour bloquer à l'entrée ce qui n'a rien à faire dans le dépôt.
15. Fiche à retenir#
- Microsoft recommande feature branches + PR +
maintoujours sain ; release branches seulement pour plusieurs versions. - Release Flow : corriger dans
main, puis cherry-pick versrelease/*; verrouiller en fin de support. - Azure Repos : une policy suffit pour rendre la PR obligatoire et interdire la suppression de la branche.
- Policies : minimum reviewers, linked work items, comment resolution, limit merge types, build validation, status checks, automatically included reviewers.
- GitHub : branch protection rule (une par branche) ou rulesets (cumulables, la plus restrictive gagne, bypass list).
- CODEOWNERS :
.github/, racine,docs/; dernière règle qui correspond ; propriétaires en write. - Merge types Azure Repos : basic (no-ff), squash, rebase + fast-forward, rebase + merge commit (semi-linéaire).
- Bypass policies (PR, push) et Force push : aucun groupe par défaut, à réserver à très peu de personnes.
- Gros binaires changeant souvent → Git LFS (gratuit, pas de SSH) ; serveur maison → git-fat (rsync) ; dépendances → Artifacts.
- Limites Azure Repos : fichier 100 Mo, dépôt < 10 Go conseillé (250 Go max), push 5 Go ; policy Maximum file size.
- Gros dépôts : Scalar (partial clone, sparse-checkout, prefetch), shallow fetch en CI.
- Tags : annotés au portail, lightweight en CLI ;
git push origin <tag>; supprimer = Force push. - Récupérer :
git reflog,git fsck --lost-found,git checkout <sha>^ -- fichier, Restore branch au portail. - Secret poussé : révoquer d'abord, puis git filter-repo ou BFG, force push, re-clone.
- Azure Repos est append-only : la vraie suppression passe par la recréation du dépôt.
Références#
Toutes lues le 21/10/2026 (Microsoft Learn sauf mention) :
- Study guide for Exam AZ-400
- Adopt a Git branching strategy
- About branches and branch policies
- Set and manage branch policies
- Set Git repository settings and policies
- Secure repositories and pull requests
- az repos policy merge-strategy
- Set Git repository permissions
- Set branch permissions
- Default Git repository and branch permissions
- Lock a branch
- Work with large files in your Git repo
- Git limits
- Optimize repository performance
- Repository health
- Pipeline options for Git repositories
- Use Git tags
- Restore a deleted Git branch from the web portal
- Remove a large binary from your Git history
- Set up secret scanning (push protection)
- Training : Manage and configure repositories (unités Scalar, recover, purge, permissions GitHub, tags GitHub)
- Repository Scalability Improved (release notes sprint 273)
- Complete post-migration tasks (Enterprise Live Migrations)
- GitHub Docs : About rulesets, About protected branches, About code owners
- git-fat (GitHub, jedbrown/git-fat) · git-filter-repo · BFG Repo-Cleaner