La lliçó anterior va acabar amb la nota que el mateix Vincent Driessen va afegir al seu article deu anys després: per a desenvolupament web continu, Git Flow és massa. Aquesta lliçó explica què hi ha a l'altra banda d'aquesta recomanació.
GitHub Flow és el model minimalista. Va néixer de la pràctica interna de GitHub i el va formalitzar Scott Chacon el 2011 en un article titulat, sense embuts, "GitHub Flow", amb una premissa que en aquell moment era gairebé una provocació: per a molts projectes, n'hi ha prou amb una sola branca de vida llarga.
I convé entendre bé d'on surt aquesta afirmació. No és simplificar per comoditat. És que Git Flow resol un problema —coordinar diverses versions publicades i una fase d'estabilització— que molts projectes no tenen. Si la teva aplicació es desplega des d'un servidor que controles tu, si només hi ha una versió en producció en cada moment, i si pots publicar un arranjament vint minuts després d'escriure'l, aleshores develop, release/* i hotfix/* no et resolen res: et cobren complexitat a canvi de res.
A gestor-tasques hi conviuen les dues realitats. L'empresa ven la versió instal·lable —i per a aquesta mantenen Git Flow, com vam veure— però també opera una versió al núvol, app.exemple.cat, que despleguen ells mateixos diverses vegades per setmana. Per a aquesta segona línia, l'equip ha decidit provar GitHub Flow.
Contingut
- La idea en una frase
- Les sis regles
- El cicle complet, amb graf
- La restricció que ho sosté tot:
mainsempre desplegable - Què exigeix a canvi
- El mètode d'integració: fusió, squash o rebase
- Versions sense branques de versió: etiquetes sobre
main - Branques protegides: el mecanisme que fa complir el flux
- Quan encaixa GitHub Flow
- Els seus límits
- La idea en una frase
Hi ha una única branca de vida llarga,
main, que està sempre en estat desplegable. Tota la resta són branques curtes que surten demain, es revisen en una pull request i tornen amain.
Això és tot el model. No hi ha develop, no hi ha release/*, no hi ha hotfix/*. Un arranjament urgent no necessita una classe de branca pròpia perquè qualsevol branca és igual de ràpida: surt de main, es revisa, entra i es desplega. La distinció entre «correcció urgent» i «funcionalitat normal» desapareix del model de branques i passa a ser, com a molt, una etiqueta al tiquet.
La comparació de topologies, sense entrar encara en la comparació completa que farem a la lliçó 07-05:
| Git Flow | GitHub Flow | |
|---|---|---|
| Branques permanents | 2 (main, develop) |
1 (main) |
| Classes de branca de suport | 3 (feature, release, hotfix) |
1 (branca de treball) |
| Regles d'origen i destinació | 5 combinacions diferents | 1: de main a main |
| Integracions dobles | Sí (release, hotfix) |
Cap |
I una conseqüència que es nota des del primer dia: és impossible oblidar-se de la segona integració, perquè no existeix.
- Les sis regles
Chacon les va enunciar així. Les reproduïm amb el que significa cadascuna a la pràctica.
Regla 1: tot el que hi ha a main és desplegable
No «compila». No «gairebé hi és». Desplegable: si ara mateix algú desplega main a producció, el resultat és correcte. És la regla de la qual depenen les altres cinc, i li dediquem tot l'apartat 4.
Regla 2: crea branques amb noms descriptius a partir de main
Sempre des de main, sempre actualitzat. El nom ha d'explicar la feina a algú que només vegi la llista de branques: segueix les convencions de la lliçó 03-06 —funcionalitat/, correccio/, documentacio/— i evita proves, temporal o branca-de-ana.
Regla 3: envia a la branca amb nom constantment
git commit -am "Filtra la llista per l'etiqueta seleccionada"
git push -u origin funcionalitat/filtre-per-etiquetaNo una vegada al final: sovint. Tres motius, i tots tres són pràctics:
- Còpia de seguretat. Si el portàtil del Bruno mor aquesta tarda, la feina és al servidor.
- Visibilitat. La resta de l'equip veu en què s'està treballant i no duplica esforços.
- La CI s'executa a cada enviament (lliçó 07-06). Una fallada detectada al cap de deu minuts costa minuts; la mateixa fallada detectada tres dies després costa hores de reconstruir el context.
Regla 4: obre una pull request en qualsevol moment
En qualsevol moment, inclosos el primer dia i el primer commit. Aquesta regla desconcerta molta gent: per què obrir una PR d'una cosa sense acabar?
Perquè la PR no és només una petició d'integrar: és el lloc on viu la conversa (lliçó 07-01). Obrir-la aviat serveix per demanar opinió sobre l'enfocament abans d'invertir-hi tres dies, per deixar constància d'on ets, perquè la CI ho provi, i perquè algú et pugui dir «això ja ho va fer la Carla en un altre lloc» abans no sigui tard. Per això hi ha les pull requests en esborrany.
Regla 5: integra només després de la revisió
Res no entra a main sense que una altra persona ho hagi mirat (lliçó 07-02). I sense que la CI estigui en verd. Aquests dos requisits no depenen de la bona voluntat: s'imposen tècnicament amb branques protegides (apartat 8).
Regla 6: desplega immediatament després d'integrar
Fusionar a main i desplegar són, idealment, el mateix acte. Com més curt sigui el buit entre les dues coses, millor: si alguna cosa va malament, saps exactament quin canvi ho ha provocat, perquè només n'ha entrat un.
Una variant freqüent a la pràctica inverteix l'ordre: desplegar la branca primer i fusionar després de comprovar que funciona en producció. És el que fa GitHub internament. Té l'avantatge que
mainno arriba mai a contenir res trencat, i el cost de necessitar infraestructura per desplegar branques arbitràries. La mecànica d'aquell desplegament —entorns, promoció, reversió— és matèria de la lliçó 10-05; aquí ens quedem en la part que toca a Git.
- El cicle complet, amb graf
gitGraph commit id: "C1" tag: "desplegament" branch funcionalitat/filtre-per-etiqueta checkout funcionalitat/filtre-per-etiqueta commit id: "F1" commit id: "F2" checkout main merge funcionalitat/filtre-per-etiqueta tag: "desplegament" branch correccio/focus-despres-esborrar checkout correccio/focus-despres-esborrar commit id: "B1" checkout main merge correccio/focus-despres-esborrar tag: "desplegament" branch funcionalitat/exportacio-csv checkout funcionalitat/exportacio-csv commit id: "E1" commit id: "E2" checkout main merge funcionalitat/exportacio-csv tag: "desplegament"
Compara'l mentalment amb el graf de la lliçó anterior. Aquí no hi ha doble carril, no hi ha ponts entre branques permanents, no hi ha fase d'estabilització. Una línia recta amb branques curtes penjant, i un desplegament a cada punt de trobada.
El cicle complet de l'Ana, de principi a fi:
# 1. Partir de main actualitzat
git switch main
git pull
# 2. Branca amb nom descriptiu
git switch -c funcionalitat/filtre-per-etiqueta
# 3. Treballar i enviar sovint
git commit -am "Afegeix el selector d'etiquetes a la barra superior"
git push -u origin funcionalitat/filtre-per-etiqueta
# ... mes commits, mes enviaments
# 4. Obrir la PR (en esborrany si encara no esta llesta)
# 5. Revisio: aplicar els comentaris a la mateixa branca
git commit -am "Conserva el filtre en recarregar la pagina"
git push
# 6. CI en verd + aprovacio -> integrar des de la plataforma
# 7. Neteja
git switch main
git pull
git branch -d funcionalitat/filtre-per-etiquetaUn detall que importa més del que sembla: la branca hauria de durar dies, no setmanes. Si una branca de GitHub Flow porta tres setmanes oberta, el model ha deixat de funcionar: has reconstruït una branca de vida llarga amb un altre nom, i amb ella tots els problemes d'integració tardana que criticàvem a la lliçó anterior. La lliçó 07-05 portarà aquesta idea a l'extrem.
Mantenir la branca al dia
Com que main avança mentre treballes, i la branca és curta, això sol ser trivial:
git switch funcionalitat/filtre-per-etiqueta
git fetch origin
git rebase origin/main # historial lineal
# o
git merge origin/main # sense reescriureMolts equips configuren la plataforma per exigir que la branca estigui actualitzada amb main abans de poder integrar. És una garantia addicional (la CI haurà provat la combinació real) a canvi d'haver d'actualitzar la branca quan algú se t'avança. En equips amb molta activitat, aquesta exigència genera una cursa contínua que es resol amb una merge queue, que veurem a la lliçó 07-06.
- La restricció que ho sosté tot:
main sempre desplegable
main sempre desplegableAquest apartat és el que cal entendre de debò. La resta és procediment.
GitHub Flow sembla més simple que Git Flow perquè té menys branques. Però no és gratis: ha canviat complexitat de procés per una restricció molt forta. Git Flow et permetia tenir develop trencat durant tres dies perquè l'estabilització passava després, a la branca de versió. GitHub Flow elimina aquella xarxa de seguretat. No hi ha branca de versió. No hi ha fase de QA posterior. main és el que es desplega, i punt.
Pensa en el que això implica:
- Si
mainestà trencat, ningú no pot desplegar. Ni la persona que ho ha trencat ni cap altra. Tot l'equip està bloquejat. - Si
mainestà trencat i no es detecta, es desplega trencat. - I si
mainestà trencat, tampoc no es pot publicar un arranjament urgent, perquè l'arranjament sortiria acompanyat del que està trencat.
D'aquí ve la regla informal més important d'aquest model: arreglar main és la màxima prioritat de l'equip, per davant de qualsevol funcionalitat. Si la CI de main es posa en vermell, s'atura el que s'estigui fent fins a tornar al verd. Molts equips apliquen una política de reversió automàtica: si main es trenca i no s'arregla en deu minuts, es reverteix el commit culpable (git revert, lliçó 05-06) i s'investiga amb calma en una branca. Revertir primer, entendre després.
I una altra conseqüència menys òbvia: la mida del desplegament baixa molt. Si desplegues després de cada PR, cada desplegament conté un canvi. Quan alguna cosa falla en producció, la llista de sospitosos té un element. Compara-ho amb desplegar una versió trimestral amb cent vint canvis a dins: quan alguna cosa va malament, comença l'arqueologia. Aquesta reducció del risc per desplegament és el benefici real del model, i és el que compensa la restricció.
- Què exigeix a canvi
La restricció de la regla 1 no se sosté sola. Exigeix tres coses, i si en falta alguna, el model no funciona: es degrada en «empenyem cap a main i preguem».
Exigència 1: proves automàtiques fiables
És la condició imprescindible. Ningú no pot garantir manualment que main sigui desplegable després de cada fusió: cal una bateria de proves que s'executi a cada enviament i a cada PR (lliçó 07-06).
I fiables és la paraula clau. Una bateria que falla aleatòriament una de cada deu execucions —el que s'anomena una prova flaky— és pitjor que no tenir proves, perquè ensenya l'equip a ignorar les fallades. Tan bon punt algú diu «torna-ho a llançar, de vegades falla», el senyal ha mort i amb ell la garantia que main és desplegable.
Exigència 2: pull requests petites
Ja ho vam quantificar a la lliçó 07-02: per sobre d'uns quants centenars de línies, la revisió deixa de detectar defectes. En un model on la revisió és l'última barrera abans de producció, això és directament risc.
A més, una PR petita es revisa el mateix dia, s'integra el mateix dia i es desplega el mateix dia. Una PR de mil línies espera tres dies que algú tingui una estona, i en aquells tres dies acumula conflictes.
Exigència 3: integració freqüent
Branques de dies, no de setmanes. És la mateixa idea que l'exigència anterior vista des del temps en lloc de la mida: com més temps viu una branca separada, més divergeix, més conflictes genera i més triga a arribar el valor a l'usuari.
I si la feina és gran de debò i no es pot trossejar en PRs petites? Hi ha resposta —banderes de funcionalitat i branch by abstraction— i és un dels temes centrals de la lliçó 07-05.
El parany d'adoptar el model sense les exigències
Val la pena dir-ho clar, perquè és el fracàs més habitual: un equip llegeix que GitHub Flow és «més simple», elimina develop i les branques de versió, i no inverteix en proves automàtiques. El resultat no és simplicitat: és que main està trencat la meitat del temps i ningú no gosa desplegar. Han tret la xarxa de seguretat de Git Flow sense construir la de GitHub Flow.
GitHub Flow no és Git Flow menys branques. És Git Flow menys branques més automatització.
- El mètode d'integració: fusió, squash o rebase
En tancar una pull request cal decidir com entren aquells commits a main. Les plataformes ofereixen tres opcions, i l'elecció determina com serà l'historial del projecte per sempre.
Tot això ja ho coneixes dels mòduls 3 i 5: aquí només veiem què produeix cada opció en el context d'una PR.
Opció A: fusió normal (merge commit)
Equival a git merge --no-ff (lliçó 03-03). Es conserven tots els commits de la branca i s'hi afegeix un commit de fusió.
gitGraph commit id: "C1" branch branca checkout branca commit id: "F1" commit id: "F2" commit id: "F3" checkout main merge branca id: "M"
Opció B: squash (condensat)
Equival al merge --squash de la lliçó 03-04. Tots els commits de la branca es condensen en un de sol sobre main, i la branca original desapareix de l'historial.
gitGraph commit id: "C1" commit id: "F (tot condensat)"
Opció C: rebase and merge
Equival a un git rebase (lliçó 05-01) seguit d'un fast-forward. Els commits es reescriuen sobre la punta de main, en línia recta i sense commit de fusió.
gitGraph commit id: "C1" commit id: "F1'" commit id: "F2'" commit id: "F3'"
La comparació
| Aspecte | Fusió normal | Squash | Rebase and merge |
|---|---|---|---|
Commits a main per PR |
Tots + 1 de fusió | Exactament 1 | Tots |
| Historial | Amb ramificacions | Lineal | Lineal |
| Es veu quins commits eren una PR? | Sí, pel commit de fusió | Sí, és un sol commit | No, es barregen |
git log --first-parent |
Una línia per PR: resum excel·lent | Igual que git log |
No aporta res |
git bisect (06-02) |
Pot entrar en commits intermedis trencats | Òptim: cada pas és una PR completa | Pot entrar en commits intermedis trencats |
| Revertir la PR sencera | git revert -m 1 <fusió> |
git revert <commit>, trivial |
Cal revertir N commits |
git blame (06-03) |
Apunta al commit original, amb el seu context | Apunta al commit condensat: es perd el detall | Apunta al commit original |
| Detall històric | Màxim | Mínim: es perd el pas a pas | Màxim |
| Reescriu hashos | No | Sí | Sí |
| Exigeix disciplina en els commits | Sí: queden a la vista | No: la neteja és automàtica | Sí |
Observacions pràctiques sobre cadascuna:
El squash és el més popular en equips que fan servir GitHub Flow, i per una raó molt concreta: absorbeix els commits desordenats. Els wip, apanyat i ara si de la branca desapareixen i a main hi queda una línia neta per cada canvi integrat. El preu és real: perds el detall de com es va construir el canvi, i en una PR gran el commit resultant és un bloc enorme que git blame no sap desglossar. És l'elecció correcta si les PRs són petites; si són grans, el squash empitjora les coses.
La fusió normal ho conserva tot, però només aporta valor si els commits de la branca estaven ben construïts (lliçó 05-02). Si no, embruta main amb soroll permanent. El seu gran avantatge és git log --first-parent main: un resum perfecte del projecte, una línia per PR.
El rebase and merge dona historial lineal sense commits de fusió, però perd del tot l'agrupació: no hi ha manera de saber quins commits van arribar junts, i revertir «aquella PR» significa revertir N commits a mà. És el que menys es fa servir dels tres.
I ara el punt important:
Tria'n un i aplica'l sempre. Un repositori on cada PR s'integra amb un mètode diferent té un historial que no es pot llegir de manera consistent:
--first-parentno significa res,bisectdona resultats desiguals i ningú no sap què esperar. La decisió concreta i les seves conseqüències sobre l'historial són el contingut de la lliçó 08-02: Mantenint un Historial Net, on tractarem la política d'historial de manera completa. Aquí n'hi ha prou de saber que la decisió existeix, que es pren una vegada, i que les plataformes permeten desactivar els mètodes que no es vulguin perquè ningú no s'equivoqui.
- Versions sense branques de versió: etiquetes sobre
main
mainSense release/*, com se sap què es va publicar i quan? Amb etiquetes sobre main (lliçó 05-05).
La idea és simple: cada desplegament a producció s'etiqueta. L'etiqueta no canvia el que hi ha al repositori; afegeix un nom estable a un commit per poder-hi tornar.
# Etiqueta anotada sobre el commit desplegat
git switch main
git pull
git tag -a v2.4.0 -m "Versio 2.4.0: filtre per etiqueta i exportacio a CSV"
git push origin v2.4.0Com que no hi ha fase d'estabilització, molts equips amb desplegament freqüent abandonen SemVer per a l'aplicació —no té gaire sentit decidir si un desplegament és minor o patch quan n'hi ha quatre al dia— i fan servir etiquetes per data i seqüència:
git tag -a desplegament-2026-08-01.1 -m "Desplegament a produccio"
git push origin desplegament-2026-08-01.1| Esquema | Exemple | Quan fer-lo servir |
|---|---|---|
| SemVer | v2.4.0 |
Biblioteques, APIs públiques, qualsevol cosa amb contracte de compatibilitat |
| Data + seqüència | desplegament-2026-08-01.1 |
Aplicacions web amb diversos desplegaments diaris |
| Número incremental | build-1482 |
Quan el número el genera la mateixa CI |
El que sí que convé mantenir és SemVer per a les biblioteques, i components-ui és exactament aquest cas: altres projectes en depenen i necessiten saber si una versió trenca la compatibilitat.
Les etiquetes són a més el mecanisme natural per a tres coses quotidianes:
# Que ha entrat entre els dos ultims desplegaments?
git log --oneline v2.3.0..v2.4.0
# En quin desplegament va sortir aquest commit?
git describe --contains <hash>
# Tornar a l'estat exacte d'un desplegament per depurar
git switch --detach v2.3.0I una tercera peça que ofereixen les plataformes: els entorns de desplegament, un registre de quin commit està actiu a cada entorn. És útil, però la seva gestió és matèria de la lliçó 10-05; des del punt de vista de Git, el que hi ha és una etiqueta i una referència.
I si cal arreglar alguna cosa urgent?
Aquí GitHub Flow brilla, perquè no necessita cap mecanisme especial. L'arranjament urgent segueix exactament el mateix camí que qualsevol altre canvi:
git switch main && git pull
git switch -c correccio/perdua-de-tasques-en-filtrar
# arreglar
git commit -am "Corregeix la perdua de tasques en aplicar dos filtres"
git push -u origin correccio/perdua-de-tasques-en-filtrar
# PR, revisio rapida, CI, integrar, desplegarVint minuts de principi a fi. A Git Flow això mateix requeria una classe de branca pròpia, dues integracions i una etiqueta de pedaç. La velocitat de desplegament fa innecessari el hotfix/*: quan desplegar costa minuts, tot arranjament és un hotfix.
- Branques protegides: el mecanisme que fa complir el flux
Tot l'anterior són acords. I com vam veure a la lliçó 06-01 en parlar dels hooks de client, els acords que depenen de la disciplina humana fallen un divendres a les set de la tarda.
La peça que converteix GitHub Flow en una cosa real és la branca protegida: un conjunt de regles que el servidor aplica sobre una branca concreta i que ningú no pot saltar-se des del seu portàtil.
Les proteccions habituals sobre main:
| Protecció | Què impedeix | Quina regla del flux sosté |
|---|---|---|
| Prohibir l'enviament directe | git push origin main des d'un portàtil |
Regles 4 i 5: tot passa per PR |
| Exigir N aprovacions | Integrar sense revisió | Regla 5 |
| Exigir comprovacions en verd | Integrar amb la CI en vermell | Regla 1: main desplegable |
Exigir branca actualitzada amb main |
Integrar sense haver provat la combinació real | Regla 1 |
| Descartar aprovacions en arribar commits nous | Aprovar una versió i integrar-ne una altra | Regla 5 |
| Prohibir l'enviament forçat | git push --force sobre main |
Regla d'or (05-06) |
| Prohibir l'esborrat de la branca | Esborrar main per accident |
Sentit comú |
| Exigir converses resoltes | Integrar amb comentaris bloquejants oberts | Regla 5 |
Quan l'Ana intenta enviar directament a una main protegida, el rebuig arriba del servidor:
remote: error: GH006: Protected branch update failed for refs/heads/main. remote: error: Required status check "proves" is expected. Changes must be remote: made through a pull request. To [email protected]:equip/gestor-tasques.git ! [remote rejected] main -> main (protected branch hook declined) error: failed to push some refs to 'git.exemple.cat:equip/gestor-tasques.git'
Fixa't en l'última línia entre parèntesis: protected branch hook declined. Això és literalment un hook de servidor rebutjant l'actualització de la referència. És la família pre-receive/update que la lliçó 06-01 va deixar anunciada, i és també la resposta a la pregunta que hi va quedar oberta: això no se salta amb --no-verify, perquè --no-verify només afecta els hooks que s'executen a la teva màquina. Aquí decideix el servidor.
Ho desenvoluparem completament a la lliçó 07-06, inclòs com una comprovació d'estat es converteix en requisit obligatori. De moment, la idea que cal retenir: GitHub Flow amb branques protegides és un procés; GitHub Flow sense elles és una recomanació.
Un apunt de disseny organitzatiu: gairebé totes les plataformes permeten que certs rols se saltin les proteccions. És temptador deixar aquella porta oberta «per si de cas», però val la pena pensar-s'ho dues vegades. L'excepció es fa servir sempre en el pitjor moment possible —un incident en producció, amb pressa i sense dormir— que és justament quan més falta fan les comprovacions.
- Quan encaixa GitHub Flow
| Condició | Per què encaixa |
|---|---|
| Aplicació web o SaaS | El desplegament el controles tu; no hi ha versions en mans de l'usuari |
| Una sola versió en producció | No hi ha res a mantenir en paral·lel, així que develop sobra |
| Desplegament freqüent i barat | Fa innecessari hotfix/*: tot arranjament arriba en minuts |
| Proves automàtiques sòlides | És la condició imprescindible de la regla 1 |
| Equip petit o mitjà | Poques branques simultànies, pocs conflictes d'integració |
| Cultura de revisió establerta | La PR és l'única barrera abans de producció |
Exemples típics: aplicacions web internes, SaaS, APIs desplegades pel mateix equip, llocs estàtics, eines internes. I el cas concret d'aquest curs: app.exemple.cat, la versió al núvol de gestor-tasques.
És també, de bon tros, el model més utilitzat avui, i és el que trobaràs per defecte a la majoria de projectes de codi obert: un col·laborador extern fa un fork (lliçó 07-01), obre una branca, envia una PR contra main i ja està. Sense develop, sense branques de versió, sense més protocol del necessari.
- Els seus límits
Ser honest amb les limitacions és el que permet triar bé.
Límit 1: no serveix per mantenir versions antigues
És el límit fonamental. Si tens clients a la 1.4 i a la 2.0 i totes dues necessiten correccions de seguretat, una sola branca de vida llarga no pot representar dos estats de producció simultanis. No hi ha manera d'arreglar la 1.4 des de main, que ja és a la 2.0.
La solució pràctica és un híbrid: GitHub Flow per al desenvolupament diari més branques de manteniment creades des de les etiquetes quan calgui:
# Nomes quan un client ho necessita
git switch -c suport/1.4 v1.4.0
git cherry-pick <arranjament-de-seguretat>
git tag -a v1.4.3 -m "Versio 1.4.3: pedac de seguretat"
git push -u origin suport/1.4 --follow-tagsÉs exactament el que fa l'equip de gestor-tasques per a la versió instal·lable. I fixa't en el matís: no és «canviar a Git Flow», és afegir la peça concreta que falta quan fa falta, que sempre és millor que adoptar un model sencer per endavant.
Límit 2: exigeix una maduresa tècnica que no tots els equips tenen
Sense proves fiables i sense una CI ràpida, el model es degrada de pressa. Un equip sense aquesta base està més segur amb Git Flow, on la branca de versió dona un marge d'estabilització manual. És una conclusió incòmoda però certa: el model més simple exigeix més maduresa, no menys.
Límit 3: no diu què fer amb la feina gran
Una migració de base de dades, una reescriptura de la interfície, un canvi d'arquitectura. No caben en una branca de tres dies i no es poden integrar a mitges en una main que ha de ser desplegable. GitHub Flow no ofereix resposta; cal portar-la de fora, i aquesta resposta —banderes de funcionalitat i branch by abstraction— és un dels temes de la lliçó següent.
Límit 4: entorns regulats o amb aprovació formal
Si cada versió requereix la signatura d'un responsable de qualitat, documentació formal o una finestra de desplegament autoritzada, l'«integrar i desplegar» de la regla 6 no és aplicable tal qual. Es pot adaptar (integrar contínuament, desplegar en finestres), però aleshores main acumula canvis sense desplegar i part del benefici es perd.
Errors Habituals i Consells
Error 1: adoptar GitHub Flow sense proves automàtiques. Es treu la xarxa de Git Flow sense construir la pròpia. main acaba trencat la meitat del temps.
Error 2: branques de tres setmanes. És una branca de vida llarga amb un altre nom, amb tots els problemes d'integració tardana que el model pretenia evitar.
Error 3: deixar main trencat i continuar treballant. Bloqueja tot l'equip, incloses les correccions urgents. Arreglar main és prioritat absoluta; si triga més d'uns minuts, reverteix.
Error 4: no protegir main. Sense branques protegides el model és una recomanació que algú es passarà per alt. Amb elles és un procés.
Error 5: barrejar mètodes d'integració. Unes PRs amb squash, altres amb fusió, altres amb rebase. L'historial resultant no es pot llegir de manera consistent.
Error 6: condensar PRs enormes. El squash funciona amb PRs petites. Condensar mil línies produeix un commit que git blame no pot desglossar i que ningú no podrà entendre d'aquí a un any.
Error 7: no etiquetar els desplegaments. Sense etiquetes no hi ha manera de saber què hi havia en producció el dimarts passat ni de tornar-hi per depurar.
Error 8: crear la branca sense actualitzar main abans. git switch main && git pull primer, sempre. Partir d'una main de fa una setmana genera conflictes evitables.
Error 9: conviure amb proves inestables. Una prova que falla una de cada deu vegades ensenya l'equip a ignorar el vermell, i amb això mor la garantia de la regla 1. Arregla-la o treu-la, però no la ignoris.
Consell 1: PRs de menys de 200 línies. És el que més impacte té en la velocitat i la qualitat del flux (lliçó 07-02).
Consell 2: obre la PR el primer dia, en esborrany. La CI comença a provar abans i algú et pot corregir el rumb a temps.
Consell 3: esborra la branca en integrar. Activa-ho a la plataforma i fes servir git fetch --prune en local. Un repositori amb dues-centes branques mortes és inutilitzable.
Consell 4: desactiva a la plataforma els mètodes d'integració que no facis servir. És més fiable que confiar que ningú no s'equivoqui de botó.
Consell 5: mesura el temps de vida de les teves branques. Si la mitjana supera la setmana, no estàs fent GitHub Flow, encara que ho anomenis així.
Consell 6: afegeix branques de manteniment només quan un client real les necessiti. No adoptis Git Flow sencer per un problema que potser no tindràs mai.
Exercicis
Exercici 1: el cicle de GitHub Flow
Sobre un repositori nou amb index.html, app.js i estils.css:
- Crea
mainamb tres commits inicials i etiqueta-la com av2.3.0. - Simula tres cicles complets: branca des de
main, dos commits, tornada amainamb--no-ff, esborrat de la branca i etiqueta de desplegament. - Fes servir noms de branca amb les convencions del projecte: una
funcionalitat/, unacorreccio/i unadocumentacio/. - Mostra el graf i comprova que s'assembla al de l'apartat 3.
- Executa
git log --oneline --first-parent maini explica quina informació et dona.
Exercici 2: comparar els tres mètodes d'integració
- Crea una branca
funcionalitat/exportacioamb quatre commits, dos d'ells clarament soroll (wip,apanyat). - Fes tres còpies del repositori a
/tmp/metode-merge,/tmp/metode-squashi/tmp/metode-rebase. - A cada còpia, integra la branca amb el mètode corresponent (
merge --no-ff,merge --squash+ commit,rebase+merge --ff-only). - Compara a les tres:
git log --oneline,git log --oneline --first-parenti el nombre de commits amain. - A cada còpia, intenta revertir la funcionalitat sencera amb una sola ordre. En quina és possible?
- Executa
git blame app.jsa les tres i comenta les diferències.
Exercici 3: la simulació del hotfix
- Partint del repositori de l'exercici 1, simula una fallada en producció: crea
correccio/perdua-de-tasquesdes demain, arregla, integra i etiqueta el desplegament. - Mesura quantes ordres han calgut des del
switchinicial fins a l'etiqueta. - Compara aquest nombre amb el procediment equivalent de
hotfix/*a Git Flow (lliçó 07-03, apartat 7). Quants passos t'has estalviat i quin és el pas de Git Flow que aquí senzillament no existeix? - Ara l'altra cara: simula que un client continua a la
v2.3.0i necessita aquest mateix arranjament sense rebre res més. Creasuport/2.3des de l'etiqueta, porta-hi l'arranjament ambcherry-picki etiquetav2.3.1. - Explica per què el pas 4 no forma part de GitHub Flow i què et diu això sobre quan el model es queda curt.
Solucions
Solució 1:
mkdir /tmp/github-flow && cd /tmp/github-flow
git init -qb main
printf '<h1>Gestor de Tasques</h1>\n' > index.html
git add . && git commit -q -m "Afegeix la pagina principal"
printf 'const tasques = [];\n' > app.js
git add . && git commit -q -m "Afegeix l'estat inicial de l'aplicacio"
printf 'body { margin: 0; }\n' > estils.css
git add . && git commit -q -m "Afegeix el full d'estils base"
git tag -a v2.3.0 -m "Versio 2.3.0"# Cicle 1
git switch -qc funcionalitat/filtre-per-etiqueta
echo "function filtraPerEtiqueta(e) { /* ... */ }" >> app.js
git commit -qam "Afegeix el filtratge per etiqueta"
echo ".filtre { display: flex; }" >> estils.css
git commit -qam "Estila la barra de filtres"
git switch -q main
git merge -q --no-ff funcionalitat/filtre-per-etiqueta -m "Fusiona funcionalitat/filtre-per-etiqueta (#101)"
git branch -qd funcionalitat/filtre-per-etiqueta
git tag -a desplegament-2026-08-01.1 -m "Desplegament a produccio"# Cicle 2
git switch -qc correccio/focus-despres-esborrar
echo "// corregit: retornar el focus al camp despres d'esborrar" >> app.js
git commit -qam "Retorna el focus al camp d'entrada despres d'esborrar"
git switch -q main
git merge -q --no-ff correccio/focus-despres-esborrar -m "Fusiona correccio/focus-despres-esborrar (#102)"
git branch -qd correccio/focus-despres-esborrar
git tag -a desplegament-2026-08-01.2 -m "Desplegament a produccio"# Cicle 3
git switch -qc documentacio/installacio
printf '# gestor-tasques\n\n## Installacio\n\nObrir index.html.\n' > README.md
git add . && git commit -q -m "Documenta la installacio al README"
git switch -q main
git merge -q --no-ff documentacio/installacio -m "Fusiona documentacio/installacio (#103)"
git branch -qd documentacio/installacio
git tag -a desplegament-2026-08-02.1 -m "Desplegament a produccio"c8a2f1e Fusiona documentacio/installacio (#103) 9d4b7c3 Fusiona correccio/focus-despres-esborrar (#102) 2f8e1a6 Fusiona funcionalitat/filtre-per-etiqueta (#101) 7b3c9d2 Afegeix el full d'estils base 4a1e6f8 Afegeix l'estat inicial de l'aplicacio 1c5d2b9 Afegeix la pagina principal
--first-parent dona una línia per PR integrada: és el resum llegible del projecte. Aquest és el benefici principal d'integrar amb fusió normal.
Solució 2:
cd /tmp/github-flow
git switch -qc funcionalitat/exportacio
echo "function exporta() { /* ... */ }" >> app.js
git commit -qam "Afegeix l'esquelet de l'exportacio"
echo "// wip" >> app.js
git commit -qam "wip"
echo "function generaCSV() { /* ... */ }" >> app.js
git commit -qam "Genera el contingut CSV"
echo "// corregit el separador" >> app.js
git commit -qam "apanyat"
git switch -q main# Fusio normal
cd /tmp/metode-merge
git merge --no-ff funcionalitat/exportacio -m "Fusiona funcionalitat/exportacio (#104)"
git log --oneline main | head -6# Squash
cd /tmp/metode-squash
git merge --squash funcionalitat/exportacio
git commit -q -m "Afegeix l'exportacio a CSV (#104)"
git log --oneline main | head -6# Rebase
cd /tmp/metode-rebase
git switch -q funcionalitat/exportacio
git rebase -q main
git switch -q main
git merge -q --ff-only funcionalitat/exportacio
git log --oneline main | head -6# 4. Comparacio
for m in merge squash rebase; do
echo "== $m: $(git -C /tmp/metode-$m rev-list --count main) commits a main"
git -C /tmp/metode-$m log --oneline --first-parent -3 main
done# 5. Revertir la funcionalitat sencera
git -C /tmp/metode-merge revert -m 1 HEAD --no-edit # funciona
git -C /tmp/metode-squash revert HEAD --no-edit # funciona
git -C /tmp/metode-rebase revert HEAD~3..HEAD --no-edit # calen 4 reversionsAmb fusió i amb squash n'hi ha prou amb una ordre. Amb rebase cal revertir cada commit, perquè res no indica que fossin un conjunt.
# 6. blame
for m in merge squash rebase; do
echo "== $m"; git -C /tmp/metode-$m blame --date=short -- app.js | tail -4
doneA squash, totes les línies de la funcionalitat apunten al mateix commit i al mateix missatge: s'ha perdut la informació de quina part es va fer en quin pas.
Solució 3:
cd /tmp/github-flow
git switch -q main
git switch -qc correccio/perdua-de-tasques
echo "// corregit: no buidar l'array en combinar dos filtres" >> app.js
git commit -qam "Corregeix la perdua de tasques en aplicar dos filtres
Refs GT-341."
git switch -q main
git merge -q --no-ff correccio/perdua-de-tasques -m "Fusiona correccio/perdua-de-tasques (#105)"
git branch -qd correccio/perdua-de-tasques
git tag -a desplegament-2026-08-02.2 -m "Desplegament urgent a produccio"Sis ordres. A Git Flow: crear des de main, arreglar, pujar la versió de pedaç, fusionar a main, etiquetar, fusionar també a develop, esborrar en dos llocs. El pas que aquí no existeix és la segona integració, i és precisament el que més s'oblida i el més car quan s'oblida.
# 4. Mantenir una versio antiga: el limit del model
ARRANJAMENT=$(git log --format=%h --grep='perdua de tasques en aplicar' -1)
git switch -qc suport/2.3 v2.3.0
git cherry-pick "$ARRANJAMENT"
git tag -a v2.3.1 -m "Versio 2.3.1: pedac per a clients de la 2.3"
git switch -q main
git log --graph --oneline --all --decorate | head -20# 5.
# suport/2.3 es una SEGONA branca de vida llarga: contradiu la premissa
# de GitHub Flow. El model assumeix una sola versio en produccio.
# Tan bon punt hi ha dos estats de produccio vius, cal una peca
# que el model no te, i s'ha de manllevar de Git Flow.Conclusió
GitHub Flow és el model dominant avui, i la seva simplicitat és real però condicionada. L'essencial:
- Una sola branca de vida llarga,
main, sempre desplegable. Tota la resta són branques curtes que surten demain, es revisen en una PR i tornen amain. No hi hadevelop, nirelease/*, nihotfix/*, ni integracions dobles per oblidar. - Les sis regles:
maindesplegable; branques descriptives des demain; enviar constantment; obrir la PR en qualsevol moment; integrar només després de la revisió; desplegar immediatament després. - «
mainsempre desplegable» és la restricció que sosté el model, i no és gratis: simaines trenca, tot l'equip queda bloquejat, incloses les correccions urgents. Arreglarmainés prioritat absoluta; si triga, es reverteix. - A canvi de treure branques, el model exigeix proves automàtiques fiables, PRs petites i integració freqüent. GitHub Flow no és Git Flow menys branques: és Git Flow menys branques més automatització. Sense aquesta base, es degrada.
- El mètode d'integració —fusió normal, squash o rebase— determina l'historial per sempre: el squash absorbeix commits desordenats i és òptim per a
bisect, la fusió conserva el detall i permet--first-parent, el rebase perd l'agrupació. Tria'n un i aplica'l sempre; la política completa és a la lliçó 08-02. - Sense branques de versió, les etiquetes sobre
mainregistren què es va desplegar i quan: SemVer per a biblioteques comcomponents-ui, data i seqüència per a aplicacions amb diversos desplegaments diaris. - Els arranjaments urgents no necessiten mecanisme propi: quan desplegar costa minuts, tot arranjament és un hotfix.
- Les branques protegides converteixen l'acord en procés: prohibir l'enviament directe, exigir aprovacions i comprovacions en verd. I aquell
protected branch hook declinedés un hook de servidor, precisament allò que--no-verifyno pot tocar. - Encaixa en web i SaaS amb una sola versió en producció, desplegament freqüent i bones proves. El seu límit és mantenir versions antigues: per a això cal afegir branques de suport des de les etiquetes.
Queda una pregunta que aquest model deixa oberta. GitHub Flow demana branques curtes, però de curtes, quant? I què es fa amb la feina que no cap en tres dies? Hi ha un corrent que respon portant la idea a l'extrem: integrar al tronc almenys una vegada al dia, cada persona, sempre, i desacoblar el desplegament de la publicació amb banderes de funcionalitat perquè això sigui possible fins i tot amb feina a mitges. És el plantejament de la lliçó 07-05: Trunk Based Development, on a més compararem per fi els tres fluxos en una sola taula i construirem un arbre de decisió per triar.
Dominant Git: De Principiant a Avançat
Mòdul 1: Introducció a Git
- Què és Git?
- Instal·lant Git
- Terminologia Bàsica de Git
- El Model de Dades de Git
- Configurant Git
- Configuració Inicial
Mòdul 2: Operacions Bàsiques de Git
- Creant un Repositori
- Clonant un Repositori
- Flux de Treball Bàsic de Git
- Preparant i Confirmant Canvis
- Inspeccionant Canvis amb git diff
- Visualitzant l'Historial de Confirmacions
Mòdul 3: Branques i Fusió
- Entenent les Branques
- Creant i Canviant Branques
- Fusionant Branques
- Estratègies de Fusió
- Resolent Conflictes de Fusió
- Gestió de Branques
Mòdul 4: Treballant amb Repositoris Remots
- Entenent els Repositoris Remots
- Afegint un Repositori Remot
- Autenticació amb Repositoris Remots
- Obtenint i Baixant Canvis
- Enviant Canvis
- Rastrejant Branques
Mòdul 5: Operacions Avançades de Git
- Rebase
- Rebase Interactiu
- Cherry-Picking de Confirmacions
- Desant Canvis Temporals
- Etiquetant Confirmacions
- Revertint Confirmacions
Mòdul 6: Eines i Tècniques de Git
- Usant Git Hooks
- Git Bisect
- Git Blame
- Git Log i Àlies
- Submòduls de Git
- Múltiples Còpies de Treball amb git worktree
Mòdul 7: Estratègies de Col·laboració i Flux de Treball
- Forks i Pull Requests
- Revisions de Codi amb Git
- Flux de Treball Git Flow
- GitHub Flow
- Trunk Based Development
- Integració Contínua amb Git
Mòdul 8: Bones Pràctiques i Consells de Git
- Escrivint Bons Missatges de Confirmació
- Mantenint un Historial Net
- Ignorant Fitxers amb .gitignore
- Atributs de Fitxer amb .gitattributes
- Bones Pràctiques de Seguretat
- Consells de Rendiment
Mòdul 9: Resolució de Problemes i Depuració
- Problemes Habituals de Git
- Desfent Canvis
- Resolent Divergències amb el Remot
- Recuperant Confirmacions Perdudes
- Tractant amb Repositoris Corruptes
- Tècniques Avançades de Depuració
