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

  1. La idea en una frase
  2. Les sis regles
  3. El cicle complet, amb graf
  4. La restricció que ho sosté tot: main sempre desplegable
  5. Què exigeix a canvi
  6. El mètode d'integració: fusió, squash o rebase
  7. Versions sense branques de versió: etiquetes sobre main
  8. Branques protegides: el mecanisme que fa complir el flux
  9. Quan encaixa GitHub Flow
  10. Els seus límits

  1. 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 de main, es revisen en una pull request i tornen a main.

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.

  1. 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

git switch main
git pull
git switch -c funcionalitat/filtre-per-etiqueta

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-etiqueta

No 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 main no 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.

  1. 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-etiqueta

Un 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 reescriure

Molts 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.

  1. La restricció que ho sosté tot: main sempre desplegable

Aquest 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 main està trencat, ningú no pot desplegar. Ni la persona que ho ha trencat ni cap altra. Tot l'equip està bloquejat.
  • Si main està trencat i no es detecta, es desplega trencat.
  • I si main està 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ó.

  1. 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ó.

  1. 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
Exigeix disciplina en els commits : queden a la vista No: la neteja és automàtica

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-parent no significa res, bisect dona 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.

  1. Versions sense branques de versió: etiquetes sobre main

Sense 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.0

Com 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.0

I 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, desplegar

Vint 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.

  1. 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:

git push origin main
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.

  1. 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.

  1. 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:

  1. Crea main amb tres commits inicials i etiqueta-la com a v2.3.0.
  2. Simula tres cicles complets: branca des de main, dos commits, tornada a main amb --no-ff, esborrat de la branca i etiqueta de desplegament.
  3. Fes servir noms de branca amb les convencions del projecte: una funcionalitat/, una correccio/ i una documentacio/.
  4. Mostra el graf i comprova que s'assembla al de l'apartat 3.
  5. Executa git log --oneline --first-parent main i explica quina informació et dona.

Exercici 2: comparar els tres mètodes d'integració

  1. Crea una branca funcionalitat/exportacio amb quatre commits, dos d'ells clarament soroll (wip, apanyat).
  2. Fes tres còpies del repositori a /tmp/metode-merge, /tmp/metode-squash i /tmp/metode-rebase.
  3. A cada còpia, integra la branca amb el mètode corresponent (merge --no-ff, merge --squash + commit, rebase + merge --ff-only).
  4. Compara a les tres: git log --oneline, git log --oneline --first-parent i el nombre de commits a main.
  5. A cada còpia, intenta revertir la funcionalitat sencera amb una sola ordre. En quina és possible?
  6. Executa git blame app.js a les tres i comenta les diferències.

Exercici 3: la simulació del hotfix

  1. Partint del repositori de l'exercici 1, simula una fallada en producció: crea correccio/perdua-de-tasques des de main, arregla, integra i etiqueta el desplegament.
  2. Mesura quantes ordres han calgut des del switch inicial fins a l'etiqueta.
  3. 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?
  4. Ara l'altra cara: simula que un client continua a la v2.3.0 i necessita aquest mateix arranjament sense rebre res més. Crea suport/2.3 des de l'etiqueta, porta-hi l'arranjament amb cherry-pick i etiqueta v2.3.1.
  5. 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"
# 4 i 5
git log --graph --oneline --decorate --all
git log --oneline --first-parent main
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
for m in merge squash rebase; do cp -r /tmp/github-flow /tmp/metode-$m; done
# 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 reversions

Amb 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
done

A 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 de main, es revisen en una PR i tornen a main. No hi ha develop, ni release/*, ni hotfix/*, ni integracions dobles per oblidar.
  • Les sis regles: main desplegable; branques descriptives des de main; enviar constantment; obrir la PR en qualsevol moment; integrar només després de la revisió; desplegar immediatament després.
  • «main sempre desplegable» és la restricció que sosté el model, i no és gratis: si main es trenca, tot l'equip queda bloquejat, incloses les correccions urgents. Arreglar main é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 main registren què es va desplegar i quan: SemVer per a biblioteques com components-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-verify no 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

Mòdul 2: Operacions Bàsiques de Git

Mòdul 3: Branques i Fusió

Mòdul 4: Treballant amb Repositoris Remots

Mòdul 5: Operacions Avançades de Git

Mòdul 6: Eines i Tècniques de Git

Mòdul 7: Estratègies de Col·laboració i Flux de Treball

Mòdul 8: Bones Pràctiques i Consells de Git

Mòdul 9: Resolució de Problemes i Depuració

Mòdul 10: Git al Món Real

© Copyright 2026. Tots els drets reservats