5. Les changesets à travers les dépôts
C’est la fonctionnalité emblématique de hawser — celle qui justifie à elle seule tout l’outil. Dans ce chapitre, tu vas prendre une seule fonctionnalité qui touche plusieurs dépôts et la piloter comme un tout : une branche commune à tous, des pull requests reliées entre elles, et une fusion qui atterrit dans le bon ordre.
Une fonctionnalité, un seul flux de revue — même quand le code est réparti sur plusieurs dépôts et plusieurs forges.
🎯 Dans ce chapitre, tu vas apprendre à…
- Comprendre ce qu’est un changeset : une fonctionnalité = une branche sur N dépôts.
- Démarrer un changeset avec
haw change start— la même branche dans chaque dépôt, en un seul geste. - Suivre toute la fonctionnalité sur un seul écran avec
haw change status. - Ouvrir des PR/MR liées entre elles avec
haw change request— sur GitHub, GitLab et Bitbucket. - Fusionner dans l’ordre des dépendances avec
haw change land, pour quemainne casse jamais.
Une fonctionnalité, plusieurs dépôts : change start crée la branche partout, status agrège, request ouvre les PR reliées.
😤 1. La douleur que ça supprime
Repense à la dernière fois qu’une fonctionnalité s’étalait sur plusieurs dépôts. Tu as fait cette danse :
git checkout -b featuredans le dépôt A. Puis le dépôt B. Puis le dépôt C.- Pousser chacun. Ouvrir une PR dans A. Puis B. Puis C.
- Courir après les revues sur trois pages de PR distinctes.
- Les fusionner — et ne pas oublier que la bibliothèque partagée doit fusionner avant les services qui en dépendent, sinon
maincasse.
Rien ne reliait ces trois PR entre elles. Il n’existait aucun artefact unique qui disait “ce sont une seule fonctionnalité.” Un changeset est exactement cet artefact : une fonctionnalité = une branche à travers N dépôts, avec des PR/MR reliées et un atterrissage ordonné.
Les changesets ont besoin d’une vraie forge (GitHub, GitLab ou Bitbucket) et d’un token pour ouvrir les PR. Les étapes start et status sont locales et sans danger à essayer partout ; request et land dialoguent avec la forge. On te signalera laquelle est laquelle.
🌱 2. Démarre le changeset
Tu donnes un nom à la fonctionnalité et (optionnellement) les dépôts qu’elle touche :
haw change start FEAT-42 --repos api,billing,proto
changeset `FEAT-42` started across 3 repo(s):
proto -> change/FEAT-42
billing -> change/FEAT-42
api -> change/FEAT-42
En un seul geste, haw a créé la même branche — change/FEAT-42 par défaut — dans chacun des trois dépôts. Maintenant tu fais tes modifications et tu committes dans chaque dépôt comme du Git normal. Le nom de la branche les relie entre eux.
Quelques options utiles au démarrage :
--repos a,b,c— se limiter aux dépôts que la fonctionnalité touche (par défaut : tous les dépôts).--branch <name>— utiliser un nom de branche personnalisé au lieu dechange/<id>.--skip-branch— adopter la branche sur laquelle chaque dépôt se trouve déjà, au lieu d’en créer une.--label <l>— attacher un label (répétable) qui sera transmis aux PR/MR plus tard.
📊 3. Regarde-la prendre forme — change status
À tout moment, retrouve toute la fonctionnalité sur un seul écran :
haw change status FEAT-42
Ceci agrège, par dépôt : la branche, si chaque dépôt est dessus, s’il est sale, son HEAD — et une fois les PR existantes, l’état de revue et le statut CI de chaque PR/MR. Avant l’ouverture de toute PR, ça ressemble à ceci (lancé sur le changeset DEMO-1 de l’« À toi de jouer » ci-dessous, donc les dépôts sont les deux clones octocat) :
changeset `DEMO-1`
REPO BRANCH ON IT DIRTY HEAD PR
hello-world change/DEMO-1 yes - 7fd1a60b —
spoon-knife change/DEMO-1 yes - d0dd1f61 —
(no PR/MRs yet — open them with `haw change request DEMO-1`)
Au lieu de trois onglets de navigateur, un seul tableau de bord. C’est l’équivalent, pour un changeset, de haw status.
Astuce : Ajoute --format json à change status (il émet un document stable haw.change-status/1) quand tu veux rediriger l’état vers un autre outil ou un script :
$ haw change status DEMO-1 --format json
{
"id": "DEMO-1",
"repos": [
{
"branch": "change/DEMO-1",
"dirty": false,
"head": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d",
"missing": false,
"name": "hello-world",
"on_branch": true,
"pr": null
}
],
"schema": "haw.change-status/1"
}
🔀 4. Ouvre les pull requests — change request
Quand tes branches sont poussées et prêtes, une seule commande ouvre des PR/MR reliées entre elles — une par dépôt — sur la forge où réside chaque dépôt :
haw change request FEAT-42
Voici la partie discrètement puissante : tes dépôts n’ont pas tous à être sur la même forge. haw parle GitHub, GitLab et Bitbucket, donc une fonctionnalité qui couvre un service GitHub et une bibliothèque GitLab obtient une PR sur GitHub et une MR sur GitLab, reliées entre elles, depuis cette unique commande. Tous les labels que tu as passés à start sont transmis ici. Cible une branche de base précise avec --base <branch>.
Cette étape a besoin d’un token de forge dans ton environnement — par ex. export GITHUB_TOKEN=$(gh auth token). haw lit les tokens uniquement depuis les variables d’environnement, ne les stocke jamais. Les étapes en lecture seule (start, status) n’ont besoin d’aucun token.
🛬 5. Atterris dans l’ordre des dépendances — change land
Les revues sont faites, les checks sont au vert. Maintenant fusionne — mais dans le bon ordre. Rappelle-toi que proto est une bibliothèque partagée dont api et billing dépendent. Fusionner un service avant que sa bibliothèque n’atterrisse, c’est comme ça qu’on casse main.
haw connaît l’ordre parce que ton manifeste le déclare. Souviens-toi de la clé deps de l’exemple microservices :
[repo.gateway]
deps = ["proto"] # proto doit atterrir avant gateway
Donc land fusionne les PR/MR dans un ordre topologique stable — les dépendances d’abord — et s’arrête à la première défaillance plutôt que de laisser un fouillis à moitié fusionné :
haw change land FEAT-42
landing changeset `FEAT-42` in dependency order:
proto ✓ merged
billing ✓ merged
api ✓ merged
changeset `FEAT-42` landed.
Étape de forge — nécessite un token. Comme request, land dialogue avec la forge et requiert un token (par ex. export GITHUB_TOKEN=$(gh auth token)) ainsi que des droits de fusion sur chaque dépôt. La sortie ci-dessus est illustrative : contre les dépôts publics en lecture seule octocat qu’utilise ce cours, request/land ne peuvent ni pousser ni fusionner, donc ne t’attends pas à ces lignes sans tes propres dépôts accessibles en écriture et un token.
proto a fusionné en premier parce que tout en dépend ; les services ont suivi. Une seule commande, le bon ordre, pas de main cassé.
Une commande. Cinq dépôts fusionnés dans le bon ordre. On l’a fait.
change land fusionne les PR/MR reliées dans l’ordre topologique — les dépendances d’abord — et s’arrête à la première défaillance.
🖼️ 6. La valeur, en une seule image
one feature (FEAT-42)
│
┌────────────┼────────────┐
proto billing api ← change start: one branch across N repos
│ │ │
MR/PR PR PR ← change request: cross-linked, any forge
│ │ │
└──── land in deps order ──┘ ← change land: proto → billing → api
Tu n’as jamais perdu de vue quelles PR étaient « la fonctionnalité », tu n’as jamais fusionné dans le mauvais ordre, et tu as tout piloté depuis quatre commandes. C’est tout l’intérêt d’un changeset : une fonctionnalité multi-dépôts qui se comporte comme un changement unique et cohérent.
Astuce : Tu travailles sur plusieurs dépôts et tu veux sauter dans l’un d’eux ? haw change goto FEAT-42 <repo> affiche son chemin pour que tu puisses faire cd "$(haw change goto FEAT-42 api)". Et haw change snapshot save <name> enregistre la branche + le HEAD de chaque dépôt pour que tu puisses restaurer plus tard l’état multi-dépôts exact.
🙌 À toi de jouer
La moitié locale du flux ne nécessite aucun jeton de forge, alors essaie-la dans un espace de travail dès maintenant :
- Lance
haw change start DEMO-1 –repos hello-world,spoon-knifeet confirme que la même branchechange/DEMO-1apparaît dans les deux dépôts (jette un œil avechaw run ‘git branch –show-current’). - Lance
haw change status DEMO-1et lis l’agrégat branche/dirty/HEAD — un seul tableau de bord au lieu de deux onglets. - Maintenant esquisse-le sur papier : pour une vraie fonctionnalité couvrant une lib partagée et deux services, dans quel ordre doivent-ils
land? (La lib d’abord — c’est la clédepsqui fait son travail.)
✅ Récapitulatif
- Un changeset est une fonctionnalité à travers N dépôts : une branche partagée, des PR/MR reliées, une fusion ordonnée.
haw change start <id> --repos a,b,ccrée la même branche dans chaque dépôt.haw change status <id>agrège branche + revue + CI sur toute la fonctionnalité.haw change request <id>ouvre des PR/MR reliées entre elles sur GitHub, GitLab et Bitbucket.haw change land <id>fusionne dans l’ordre des dépendances (d’après ledepsde chaque dépôt), en s’arrêtant à la première défaillance.start/statussont locales ;request/landont besoin d’un token de forge dans l’environnement.
👉 La suite
Tu sais livrer une fonctionnalité à travers la flotte. Maintenant, compilons, testons et vérifions le tout — le workflow quotidien qui le garde au vert → 6. Compiler, tester et vérifier.