Vous en avez marre des merge conflicts monstres ? Des feature branches qui durent 3 semaines ? Des hotfixes qui cassent tout ? Il existe une alternative plus simple : le Trunk-Based Development.
Le problème avec Git Flow
Git Flow : Le standard qui ne scale pas
┌─────────┐
│ master │────────────────────────────
└─────────┘ merge merge
│
┌────▼────┐
│ develop │───────────────────
└─────────┘ merge merge
│
┌────▼────────┐
│ feature/123 │─────────
└─────────────┘
Problèmes réels :
- Merge hell : Plus la branche vit, plus les conflicts sont difficiles
- Integration tardive : On découvre les bugs à la fin
- Complexité : Develop, release, hotfix, feature… 4 types de branches
- Slow feedback : PR mergée après plusieurs jours
Chez un client :
- Feature branch moyenne : 8.5 jours
- Merge conflicts : 40% des PRs
- Time to production : 2-3 semaines
Trunk-Based Development : La solution
Principe simple
Tout le monde commit sur la même branche (trunk/main) plusieurs fois par jour.
main ───●───●───●───●───●───●───●───●───
Dev1 Dev2 Dev1 Dev3 Dev2 Dev1 Dev4
Règles :
- Commits fréquents (plusieurs fois/jour)
- Petits changements (< 400 lignes)
- CI/CD obligatoire
- Feature flags pour code incomplet
“Mais c’est dangereux !”
Objection : “On va casser la prod !”
Réponse : Pas si vous avez :
- Tests automatisés solides
- CI qui bloque si tests fail
- Feature flags
- Monitoring proactif
Les géants de la tech le font :
- Google : 25,000 engineers, 1 trunk
- Facebook : Commits toutes les 15min
- Netflix, Amazon, etc.
Migration : Notre approche progressive
Phase 1 : Réduire la durée de vie des branches
Avant :
Feature branch : 8 jours
Objectif :
Semaine 1-2 : Max 5 jours
Semaine 3-4 : Max 3 jours
Semaine 5-6 : Max 2 jours
Semaine 7+ : Max 1 jour
Comment :
- Découper features en petites tâches
- Review quotidiennes obligatoires
- Alerte automatique si branch > 2 jours
Phase 2 : Short-lived branches
main ───●────────●─────────●────────
\ / \ /
●────● ●───●
(2h) (4h)
Règles :
- Max 24h de vie
- Max 400 lignes changées
- Merge dès que CI passe
Phase 3 : Direct commits sur main (optionnel)
Réservé aux équipes très matures :
# Direct push sur main (avec protection)
git push origin main
# CI vérifie automatiquement :
# - Tests passent
# - Coverage > 80%
# - Linting OK
# - Security scan OK
# Si KO : Auto-revert
Feature Flags : La clé du succès
Sans feature flags
// ❌ Code incomplet visible en prod
function checkout() {
// Nouvelle feature pas finie
if (newPaymentFlow) {
// TODO: implémenter
}
}
Avec feature flags
// ✅ Code en prod mais invisible
import { isEnabled } from './feature-flags';
function checkout() {
if (isEnabled('new-payment-flow')) {
return newPaymentFlow();
}
return oldPaymentFlow();
}
Avantages :
- Merge code incomplet en toute sécurité
- Test en prod avec % users
- Rollback instantané (toggle flag)
- A/B testing facile
Feature flags en pratique
// feature-flags.ts
export const flags = {
'new-payment-flow': {
enabled: true,
rollout: 10, // 10% des users
targeting: {
countries: ['FR', 'BE'],
userTier: 'premium'
}
}
};
export function isEnabled(flag: string, context?: any): boolean {
const config = flags[flag];
if (!config?.enabled) return false;
// Rollout progressif
if (Math.random() * 100 > config.rollout) return false;
// Targeting
if (config.targeting) {
return matchesTargeting(context, config.targeting);
}
return true;
}
Solutions existantes :
- LaunchDarkly
- Unleash (Open Source)
- Flagsmith
CI/CD : Configuration requise
Pipeline exemple
# .github/workflows/trunk.yml
name: Trunk CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# Tests rapides d'abord (fail fast)
- name: Lint
run: npm run lint
- name: Unit tests
run: npm run test:unit
- name: Integration tests
run: npm run test:integration
# Build
- name: Build
run: npm run build
# Security
- name: Security scan
run: npm run security-check
# Deploy si main
- name: Deploy to staging
if: github.ref == 'refs/heads/main'
run: ./deploy.sh staging
# Deploy prod avec feature flags
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: ./deploy.sh production
Durée : < 10 minutes (objectif : < 5min)
Protection branch main
// GitHub branch protection
{
"branch": "main",
"protection": {
"required_status_checks": {
"strict": true,
"contexts": [
"test",
"lint",
"security-scan"
]
},
"required_reviews": {
"required_approving_review_count": 1,
"dismiss_stale_reviews": true
},
"enforce_admins": true,
"allow_force_pushes": false
}
}
Code Review : Adapter le process
Review rapides obligatoires
Avant (Git Flow) :
- Feature complète à review
- 500-1000 lignes
- Review le lendemain
- 3-4 aller-retours
Après (Trunk-Based) :
- Petit changement
- < 400 lignes
- Review dans l’heure
- 1-2 aller-retours max
Process review optimisé
09h00 : Dev1 crée PR (150 lignes)
09h30 : Dev2 review (15min)
09h45 : Dev1 corrige commentaires
10h00 : Merge + Deploy staging
10h15 : Tests smoke OK
10h30 : Deploy production (feature flag 5%)
Temps total : 1h30 au lieu de 2 jours
Review checklist
## PR Checklist
### Size
- [ ] < 400 lignes changées
- [ ] 1 feature/fix par PR
### Tests
- [ ] Tests unitaires ajoutés
- [ ] Coverage maintenu (>80%)
- [ ] Tests d'intégration si nécessaire
### Code Quality
- [ ] Lint passe
- [ ] Pas de code commenté
- [ ] Documentation à jour
### Feature Flags
- [ ] Feature flag si code incomplet
- [ ] Rollout progressif configuré
### Backward Compatibility
- [ ] Pas de breaking change
- [ ] Migration planifiée si besoin
Métriques de succès
Chez un client (6 mois de Trunk-Based)
Developer Experience :
- Time to merge : 2.5 jours → 4h (-94%)
- Merge conflicts : 40% → 5% PRs
- Lines changed/PR : 850 → 280 (-67%)
Quality :
- Bugs production : -35%
- Incidents : -42%
- MTTR : 2h → 25min (-79%)
Business :
- Time to production : 2 semaines → 1 jour (-93%)
- Deploys/week : 3 → 42 (+1300%)
- Developer satisfaction : 6.2 → 8.7 /10
Erreurs à éviter
Erreur 1 : Pas de feature flags
// ❌ Code incomplet pushé sans flag
function newFeature() {
// TODO: finir demain
}
Résultat : Feature cassée en prod.
Erreur 2 : PRs trop grosses
❌ PR #123: Refonte page checkout (1200 lignes)
Solution : Découper en 4-5 PRs de 250-300 lignes chacune.
Erreur 3 : Tests insuffisants
Sans tests solides, trunk-based = chaos.
Minimum requis :
- Coverage > 80%
- Tests E2E sur parcours critiques
- CI < 10 minutes
Erreur 4 : Skip code review
“On merge direct, on verra après”
Résultat : Dette technique explosive.
Solution : Review obligatoire, même pour petits changements.
Outils recommandés
Feature Flags
- Unleash (Open Source) - Self-hosted
- LaunchDarkly (SaaS) - Enterprise
- Flagsmith (Hybrid) - Flexible
CI/CD
- GitHub Actions - Simple et intégré
- GitLab CI - Complet
- CircleCI - Rapide
Monitoring
- Sentry - Error tracking
- Datadog - Observability
- Grafana - Dashboards
Trunk-Based pour différents contextes
Startup (5-10 devs)
✅ Trunk pur (direct commits)
✅ Feature flags simples
✅ CI/CD basique mais rapide
Scale-up (20-50 devs)
✅ Short-lived branches (< 24h)
✅ Feature flags avancés (targeting, rollout)
✅ CI/CD robuste avec staging
Enterprise (100+ devs)
✅ Short-lived branches + review
✅ Feature flags enterprise (LaunchDarkly)
✅ CI/CD multi-stages
✅ Canary deployments
Conclusion
Trunk-Based Development n’est pas magique.
Prérequis :
- Tests automatisés solides
- CI/CD rapide (<10min)
- Feature flags
- Culture de feedback rapide
Mais les bénéfices sont réels :
- Merge conflicts drastiquement réduits
- Time to production divisé par 10
- Qualité améliorée
- Équipe plus heureuse
Commencez progressivement :
- Réduire durée de vie branches
- Ajouter feature flags
- Accélérer CI/CD
- Passer à short-lived branches
Et vous, prêts à simplifier votre workflow Git ?