Les dues lliçons anteriors van resoldre com es proposa un canvi i com es revisa. Queda la pregunta de dalt: quines branques existeixen al repositori i per a què serveix cadascuna.

Fins ara, gestor-tasques ha viscut amb un model implícit: una branca main i branques de treball amb els prefixos que van acordar a la lliçó 03-06. Funcionava perquè l'equip desplegava l'aplicació web i prou. Però la situació ha canviat: l'empresa ha començat a vendre gestor-tasques com a producte instal·lable als servidors del client. Ara hi ha una versió 1.4 funcionant en tres clients que no es volen actualitzar, una versió 2.0 en preparació, i l'obligació de publicar correccions de seguretat per a la 1.4 sense arrossegar res de la 2.0.

Aquest escenari —versions explícites, diverses vives alhora, lliuraments planificats— és exactament per al qual es va dissenyar Git Flow, el model de ramificació que Vincent Driessen va publicar el gener del 2010 i que durant anys va ser la resposta per defecte a la pregunta «com organitzem les branques?».

Aquesta lliçó explica el model complet, sense caricaturitzar-lo i sense vendre'l. És un model amb una lògica interna impecable i amb costos reals, i totes dues coses cal entendre-les abans de decidir si convé.

Contingut

  1. El problema que resol Git Flow
  2. Les cinc classes de branca
  3. El cicle complet d'un cop d'ull
  4. develop i main: les dues branques permanents
  5. Branques de funcionalitat: obrir i tancar
  6. Branques de versió: estabilitzar sense bloquejar
  7. Branques de hotfix: per què s'integren en dos llocs
  8. On encaixen les etiquetes
  9. L'eina git flow
  10. Quan té sentit Git Flow
  11. Les crítiques, i la nota del mateix autor

  1. El problema que resol Git Flow

Abans del model, el problema. Imagina l'equip de gestor-tasques sense cap convenció de branques, a punt de publicar la versió 2.0:

  • L'Ana ha acabat l'exportació a CSV i la vol integrar.
  • La Carla és a mitja sincronització amb el calendari, que no entrarà a la 2.0.
  • En Bruno està corregint les últimes errades detectades a les proves de la 2.0.
  • I un client acaba de reportar una errada greu a la 1.4, que cal arreglar avui.

Si tothom treballa contra una sola branca, això és impossible de gestionar. La feina de la Carla no hi pot entrar encara, però tampoc pot quedar-se tres setmanes sense integrar. L'arranjament de la 1.4 no es pot construir sobre el codi de la 2.0, perquè el client no vol la 2.0.

Git Flow respon amb una idea senzilla i conseqüent: cada tipus de feina té la seva pròpia classe de branca, amb regles explícites d'on neix i on acaba. No s'improvisa res.

  1. Les cinc classes de branca

El model en defineix cinc, dividides en dos grups.

Branques permanents (existeixen sempre, mai no s'esborren):

  • main (anomenada master a l'article original): conté exclusivament codi publicat. Cada commit de main és una versió que va sortir al món, i porta la seva etiqueta. Ningú no hi confirma directament.
  • develop: la línia d'integració. Conté tot allò acabat i acceptat que sortirà a la propera versió. És l'estat «següent release».

Branques de suport (neixen, compleixen la seva funció i s'esborren):

  • feature/*: una funcionalitat en desenvolupament.
  • release/*: la preparació i estabilització d'una versió concreta.
  • hotfix/*: una correcció urgent sobre el que hi ha en producció.

La taula completa, que és la referència pràctica del model:

Branca Neix de S'integra a Permanent? Nom habitual
main main / master
develop main (un cop, a l'inici) develop
feature/* develop develop No feature/exportacio-csv
release/* develop main i develop No release/2.0.0
hotfix/* main main i develop No hotfix/2.0.1

Hi ha dues files que concentren gairebé tota la complexitat del model, i convé fixar-s'hi des d'ara:

  1. hotfix/* neix de main, no de develop. És l'única classe que ho fa, i és la raó de ser del model: per arreglar el que és en producció cal partir del que és en producció, no del codi en desenvolupament que porta quinze funcionalitats a mitges.
  2. release/* i hotfix/* s'integren en dos llocs. Aquesta doble integració és el que garanteix que no es perdi res, i és també la font de les errades més cares del model (apartat 7).

A gestor-tasques, l'equip ja fa servir els prefixos funcionalitat/, correccio/, documentacio/ i hotfix/ (lliçó 03-06). Git Flow proposa feature/, release/ i hotfix/. El nom concret és igual: el que importa és que a cada classe li correspongui un paper i que tothom el conegui. Farem servir els noms canònics del model perquè reconeguis la terminologia quan la vegis a fora.

  1. El cicle complet d'un cop d'ull

Aquest graf recull el cicle sencer: dues funcionalitats, una versió i un hotfix posterior.

gitGraph
   commit id: "inicial" tag: "v1.4.0"
   branch develop
   checkout develop
   commit id: "arrencada develop"
   branch feature/exportacio-csv
   checkout feature/exportacio-csv
   commit id: "F1"
   commit id: "F2"
   checkout develop
   merge feature/exportacio-csv
   branch feature/ordre-alfabetic
   checkout feature/ordre-alfabetic
   commit id: "G1"
   checkout develop
   merge feature/ordre-alfabetic
   branch release/2.0.0
   checkout release/2.0.0
   commit id: "pujar versio a 2.0.0"
   commit id: "corregir errada de QA"
   checkout main
   merge release/2.0.0 tag: "v2.0.0"
   checkout develop
   merge release/2.0.0
   checkout main
   branch hotfix/2.0.1
   checkout hotfix/2.0.1
   commit id: "arreglar esborrat massiu"
   checkout main
   merge hotfix/2.0.1 tag: "v2.0.1"
   checkout develop
   merge hotfix/2.0.1

Llegeix-lo de dalt a baix i queda't amb la forma general:

  • main és una línia curta de fites etiquetades. Cinc commits l'any, potser. Cadascun, una versió.
  • develop és la línia de treball continu, on desemboca tot el que està acabat.
  • Les branques de funcionalitat surten i tornen a develop.
  • Les branques de versió surten de develop i desemboquen a les dues permanents.
  • Les de hotfix surten de main i també desemboquen a totes dues.

Aquesta forma de «doble carril amb ponts» és la signatura visual de Git Flow. Si veus un graf així, ja saps quin model segueix el projecte.

  1. develop i main: les dues branques permanents

main és un registre, no un lloc de treball

La regla és absoluta: a main només hi entren fusions de release/* i de hotfix/*. Cap commit directe, cap funcionalitat, cap correcció que no vingui per un d'aquests dos camins.

La conseqüència pràctica és molt valuosa: git log --oneline main és literalment l'historial de versions del producte, i git checkout v1.4.0 reconstrueix exactament el que té instal·lat el client. Això és el que permet depurar una errada reportada per un client concret sense endevinalles.

git log --oneline --first-parent main
8f3c2a1 Fusiona la branca hotfix/2.0.1
4d9e7b3 Fusiona la branca release/2.0.0
b1a6f28 Fusiona la branca hotfix/1.4.1
7c2d5e9 Fusiona la branca release/1.4.0

El --first-parent (lliçó 06-04) mostra només la línia principal, ignorant el que va entrar per cada fusió.

develop és la sala d'espera de la propera versió

Tot el que està acabat s'hi integra. I aquí hi ha la primera restricció important del model, que convé dir en veu alta:

develop no està garantit com a desplegable. Està garantit com a integrat.

És una diferència substancial amb els models que veurem després. A Git Flow, la garantia de qualitat no s'aplica a develop: s'aplica a la branca de versió, que és on s'estabilitza. develop pot tenir funcionalitats a mig polir, canvis que no s'han provat junts i regressions que encara ningú no ha detectat. És un estat intermedi, i el model ho assumeix.

Creació inicial, en un projecte que arrenca des de main:

git switch main
git switch -c develop
git push -u origin develop

I un detall operatiu important: a la plataforma, la branca per defecte del repositori ha de ser develop, no main. Així les pull requests apunten per defecte al lloc correcte i els clons nous aterren on es treballa. És un ajust d'un minut que evita desenes de PRs obertes contra la branca equivocada.

  1. Branques de funcionalitat: obrir i tancar

És el cicle més freqüent i el més simple.

Obrir

git switch develop
git pull                                  # partir de l'ultim integrat
git switch -c feature/exportacio-csv

Neix de develop, sempre. Néixer de main és l'error clàssic del principiant en aquest model: t'emportes una base sense les últimes funcionalitats i acabes amb conflictes en integrar.

Treballar

Commits normals, tants com calgui. Enviar a origin si la feina dura més d'un dia o si cal col·laborar:

git push -u origin feature/exportacio-csv

Tancar

Quan la funcionalitat està acabada i revisada (lliçons 07-01 i 07-02), s'integra a develop:

git switch develop
git pull
git merge --no-ff feature/exportacio-csv
git push origin develop
git branch -d feature/exportacio-csv
git push origin --delete feature/exportacio-csv

El --no-ff no és opcional a Git Flow, és part del model. Recorda de la lliçó 03-03 que sense ell, si develop no ha avançat, Git faria un fast-forward i els commits de la funcionalitat quedarien diluïts a la línia principal sense deixar rastre que formaven un conjunt. Amb --no-ff es crea sempre un commit de fusió, i això proporciona tres coses:

  • El graf mostra quins commits pertanyien a quina funcionalitat.
  • Es pot revertir la funcionalitat sencera amb git revert -m 1 <fusió> (lliçó 05-06).
  • git log --first-parent develop dóna la llista de funcionalitats integrades, una línia per cadascuna.

Si l'equip treballa amb pull requests, la plataforma fa aquest merge --no-ff per tu en prémer el botó d'integrar.

Mantenir-se al dia durant el desenvolupament

Si develop avança molt mentre treballes, actualitza la teva branca per no acumular conflictes:

git switch feature/exportacio-csv
git rebase develop           # historial lineal; nomes si la branca no es compartida
# o be
git merge develop            # sense reescriure; segur sempre

L'elecció entre totes dues és política del projecte i es tracta a la lliçó 08-02. El que no s'ha de fer és deixar la branca sense actualitzar durant setmanes: aquest és el mecanisme pel qual Git Flow acumula conflictes grans, del qual parlarem a l'apartat 11.

  1. Branques de versió: estabilitzar sense bloquejar

Aquesta és la classe de branca que més gent no entén, i la que justifica tot el model.

El problema que resol: arriba el moment de publicar la 2.0. Cal pujar el número de versió als fitxers, actualitzar el README.md i el registre de canvis, passar la bateria de proves manuals, corregir el que aparegui. Això dura una setmana. Durant aquella setmana, què fa la resta de l'equip? Si tothom espera, es perd una setmana de feina de tres persones. Si continuen integrant a develop, la versió no es congela mai perquè sempre hi entra alguna cosa nova.

La solució: s'obre una branca release/2.0.0 des de develop. A partir d'aquell instant:

  • La versió 2.0 és exactament el que hi ha en aquella branca. Està congelada.
  • develop queda lliure immediatament per rebre la feina de la 2.1.
  • A la branca de versió només hi entren correccions d'errades i ajustos de publicació. Cap funcionalitat nova. Cap.
# Obrir la branca de versio
git switch develop
git pull
git switch -c release/2.0.0

# Ajustos propis de la publicacio
# (editar el numero de versio als fitxers del projecte)
git commit -am "Puja la versio a 2.0.0"

# (actualitzar CHANGELOG.md amb el que entra en aquesta versio)
git commit -am "Actualitza el registre de canvis per a la 2.0.0"

git push -u origin release/2.0.0

Durant els dies següents, les proves revelen errades i es corregeixen en aquesta branca:

git switch release/2.0.0
git commit -am "Corregeix el desbordament del titol llarg a la vista mobil"
git push origin release/2.0.0

El tancament: la doble integració

Quan la versió està llesta, s'integra a main i a develop:

# 1. A main, que es el que es publica
git switch main
git pull
git merge --no-ff release/2.0.0 -m "Fusiona la branca release/2.0.0"

# 2. Etiquetar la versio (llico 05-05): anotada i signada
git tag -a v2.0.0 -m "Versio 2.0.0

Exportacio a CSV, ordre alfabetic configurable i
sincronitzacio amb calendari."

git push origin main --follow-tags
# 3. I de tornada a develop, per no perdre les correccions d'estabilitzacio
git switch develop
git pull
git merge --no-ff release/2.0.0 -m "Fusiona la branca release/2.0.0 a develop"
git push origin develop

# 4. Esborrar la branca
git branch -d release/2.0.0
git push origin --delete release/2.0.0

El pas 3 és el que s'oblida, i la seva conseqüència és desagradable: les cinc correccions que es van fer durant l'estabilització existeixen a main però no a develop. És a dir, la versió 2.1 reintroduirà les cinc errades que acabes d'arreglar. Apareixeran com a «regressions misterioses» i costaran un dia sencer de git bisect (lliçó 06-02) fins que algú entengui què va passar.

Com comprovar que no ha passat:

# Hi ha res a main que no sigui a develop?
git log --oneline develop..main

Si aquella ordre retorna alguna cosa diferent dels commits de fusió propis de main, tens feina pendent. Val la pena convertir-ho en una comprovació automàtica del CI (lliçó 07-06).

Quan obrir la branca de versió?

Quan develop conté l'abast previst per a aquella versió. El criteri no és temporal, és de contingut. I una precisió: obrir la branca aviat és millor que tard, perquè allibera develop abans. Molts equips l'obren tan bon punt l'última funcionalitat prevista està integrada, encara que falti tota la fase de proves.

  1. Branques de hotfix: per què s'integren en dos llocs

Escenari: la 2.0.0 porta tres dies en producció i un client descobreix que el botó d'esborrat massiu elimina també les tasques completades d'altres usuaris. És greu. Cal arreglar-ho avui.

I aquí hi ha el punt crític del model: no es pot publicar el que hi ha a develop. develop ja porta quatre funcionalitats de la 2.1 sense provar. Publicar això per arreglar una errada seria canviar un problema per cinc.

La solució de Git Flow: partir de main, que és exactament el que el client té instal·lat.

# 1. Neix de main, a l'etiqueta de la versio afectada
git switch main
git pull
git switch -c hotfix/2.0.1

# 2. L'arranjament minim. Res mes.
git commit -am "Corregeix l'esborrat massiu que afectava tasques alienes

El filtre per usuari no s'aplicava a esborraCompletades().
Refs GT-318."

# 3. Pujar el numero de versio de pedac
git commit -am "Puja la versio a 2.0.1"
git push -u origin hotfix/2.0.1

I el tancament, també doble:

# A main, amb la seva etiqueta
git switch main
git merge --no-ff hotfix/2.0.1 -m "Fusiona la branca hotfix/2.0.1"
git tag -a v2.0.1 -m "Versio 2.0.1: corregeix l'esborrat massiu"
git push origin main --follow-tags

# A develop, perque l'arranjament no es perdi
git switch develop
git merge --no-ff hotfix/2.0.1 -m "Fusiona la branca hotfix/2.0.1 a develop"
git push origin develop

git branch -d hotfix/2.0.1
git push origin --delete hotfix/2.0.1

La raó de la doble integració, dita explícitament: si l'arranjament només entrés a main, la propera versió sortiria de develop, que no el té, i l'errada tornaria. El client veuria reaparèixer a la 2.1 el mateix problema que li vas arreglar a la 2.0.1. És l'error més car que es pot cometre amb aquest model, perquè destrueix la confiança del client.

Un cas especial: hotfix mentre hi ha una versió oberta

Si en aquell moment existeix una release/2.1.0 en estabilització, l'arranjament ha d'arribar a totes tres: main, release/2.1.0 i develop. La regla pràctica: s'integra a main i a la branca de versió oberta; develop el rebrà quan aquella versió es tanqui. I si prefereixes no raonar-ho cada vegada, fes servir git cherry-pick (lliçó 05-03) per portar el commit de l'arranjament allà on falti, i comprova després amb git log --oneline <branca>..main.

Si cal arreglar una versió antiga

El client que continua a la 1.4 també necessita l'arranjament, i main és a la 2.0.1. Aquí el model canònic es queda curt i la pràctica habitual és tenir una branca de manteniment de vida llarga:

# Branca de manteniment creada des de l'etiqueta corresponent
git switch -c suport/1.4 v1.4.0

# Portar l'arranjament que ja existeix a main
git cherry-pick <hash-de-l-arranjament>
git tag -a v1.4.2 -m "Versio 1.4.2: corregeix l'esborrat massiu"
git push -u origin suport/1.4 --follow-tags

Aquesta capacitat de mantenir diverses versions vives alhora és la raó principal per la qual un producte instal·lable tria Git Flow. Cap altre model no ho fa tan bé.

  1. On encaixen les etiquetes

Les etiquetes de la lliçó 05-05 tenen a Git Flow un lloc exacte i sense ambigüitat:

Cada commit de fusió a main rep una etiqueta anotada amb el número de versió. Cap altra branca no s'etiqueta.

Origen de la fusió a main Etiqueta Component de SemVer que canvia
release/2.0.0 amb funcionalitats noves v2.0.0 o v2.1.0 major o minor
hotfix/2.0.1 v2.0.1 patch

I l'encaix amb SemVer és gairebé automàtic: release/* puja minor (o major si trenca compatibilitat), hotfix/* puja patch sempre. Per això el nom de la branca inclou el número de versió: release/2.1.0 et diu quina etiqueta produirà abans d'obrir-la.

Recorda de la 05-05 les dues regles que aquí importen:

  • Etiquetes anotades (git tag -a), no lleugeres: porten autor, data i missatge, i són objectes reals del repositori.
  • Les etiquetes no s'envien soles. git push origin main no se les emporta. Fes servir --follow-tags (envia les anotades accessibles des del que envies) o git push origin v2.0.1.

Comprovacions útils sobre l'historial de versions:

# Totes les versions publicades, en ordre
git tag -l 'v*' --sort=-v:refname

# Que va canviar entre dues versions
git log --oneline v2.0.0..v2.0.1

# En quina versio es va publicar per primer cop un commit
git describe --contains <hash>

# Versio actual llegible, util per al numero de build
git describe --tags

  1. L'eina git flow

Existeix una extensió de línia d'ordres, git-flow (originalment de Vincent Driessen, avui mantinguda sobretot a la variant AVH), que automatitza les seqüències dels apartats anteriors.

# Installacio
sudo apt install git-flow          # Ubuntu — Ana
brew install git-flow-avh          # macOS — Bruno
# Windows — Carla: inclos al Git for Windows, o via Chocolatey
# Inicialitzar al repositori (pregunta els noms de branca i prefixos)
git flow init

Les ordres i la seva traducció exacta al que ja saps:

Ordre de git flow El que fa realment
git flow feature start exportacio-csv git switch -c feature/exportacio-csv develop
git flow feature publish exportacio-csv git push -u origin feature/exportacio-csv
git flow feature finish exportacio-csv switch develop + merge --no-ff + branch -d
git flow release start 2.0.0 git switch -c release/2.0.0 develop
git flow release finish 2.0.0 merge a main + tag + merge a develop + esborrar branca
git flow hotfix start 2.0.1 git switch -c hotfix/2.0.1 main
git flow hotfix finish 2.0.1 merge a main + tag + merge a develop + esborrar branca

Insistim en una cosa important: git flow no afegeix cap capacitat a Git. És sucre sintàctic sobre switch, merge, tag, push i branch -d. No hi ha estat ocult ni màgia; l'única cosa que desa és la configuració de noms de branca a .git/config:

[gitflow "branch"]
    master = main
    develop = develop
[gitflow "prefix"]
    feature = feature/
    release = release/
    hotfix = hotfix/
    versiontag = v

Avantatges: elimina l'oblit de la segona integració, que és l'error car del model, i unifica la manera de treballar de l'equip.

Inconvenients reals, i no són menors:

  • Encaixa malament amb les pull requests. git flow feature finish fusiona en local i envia. Si el projecte exigeix revisió abans d'integrar (lliçons 07-01 i 07-02), aquella ordre se salta el procés sencer. En equips amb revisió obligatòria es fa servir git flow feature publish i després una PR normal, ignorant finish.
  • Amaga el que passa. Qui aprèn Git Flow només amb l'eina no entén el graf que està construint, i el dia que alguna cosa falla no sap per on començar.
  • És una dependència més per instal·lar en tres sistemes operatius diferents.

Consell pràctic: aprèn primer les ordres manuals, i adopta l'eina després si l'equip ho vol. A l'inrevés, no.

  1. Quan té sentit Git Flow

Git Flow té mala premsa avui, i bona part d'aquesta mala premsa ve d'haver-se aplicat en projectes per als quals no es va dissenyar. El model és bo quan es donen aquestes condicions:

Condició Per què importa
Versions explícites i numerades Tot el model gira al voltant de release/* i les etiquetes. Sense versions, main i develop són redundants
Diverses versions mantingudes alhora La combinació hotfix/* + branques de suport és la millor resposta a aquest problema
Lliuraments planificats, no continus La branca de versió té sentit si hi ha una fase d'estabilització real
L'usuari decideix quan actualitza Programari instal·lable, mòbil, encastat, biblioteques
Fase de QA manual abans de publicar La branca de versió és exactament el lloc on viu aquesta fase
Equip mitjà o gran amb rols definits Algú «gestiona la versió» com a tasca pròpia

Casos concrets on encaixa bé:

  • Programari instal·lable al client, com el gestor-tasques que l'empresa ara ven.
  • Aplicacions mòbils, on la botiga imposa un cicle de revisió i l'usuari decideix quan actualitza.
  • Biblioteques i SDK amb compromís de compatibilitat i diverses branques mantingudes (1.x, 2.x).
  • Sistemes encastats i microprogramari, on una versió dolenta no es pot retirar.
  • Entorns regulats on cada versió requereix documentació i aprovació formal.

I on encaixa malament, que és on més s'ha fet servir:

  • Aplicacions web amb desplegament continu. Si publiques cinc vegades al dia, la branca de versió és un tràmit buit i develop és una còpia de main amb un dia de retard.
  • SaaS amb una sola versió viva. No hi ha res per mantenir en paral·lel; hotfix/* no aporta res que no aporti una branca normal.
  • Equips petits. El cost de coordinació del model es reparteix entre poques persones i pesa massa.

  1. Les crítiques, i la nota del mateix autor

Les objeccions a Git Flow són serioses i convé conèixer-les abans d'adoptar-lo.

Crítica 1: complexitat

Cinc classes de branca, dues de permanents, regles diferents d'origen i destinació per a cadascuna, i dues integracions que cal recordar. És molt protocol per mantenir al cap. A la pràctica, tot equip que fa servir Git Flow acumula un document intern de «com fem les coses» i tot i així algú s'equivoca cada poques setmanes.

Crítica 2: branques de vida llarga i integració tardana

Aquesta és la crítica de fons, i va més enllà de la comoditat.

Una funcionalitat pot viure setmanes a la seva branca abans de tocar develop. I la relació entre el temps que una branca passa separada i el cost d'integrar-la no és lineal: és explosiva. Cada dia que passa, més commits a develop, més probabilitat que algú hagi tocat els mateixos fitxers, més conflictes i més difícils.

flowchart LR
    A["Branca oberta<br/>més temps"] --> B["Més divergència<br/>respecte a develop"]
    B --> C["Conflictes més grans<br/>i difícils"]
    C --> D["Por d'integrar"]
    D --> A

Aquest bucle es realimenta: com pitjor és integrar, més es posposa, i com més es posposa, pitjor és. El model no ho causa tot sol, però tampoc no empeny en contra: en no exigir integració freqüent, la permet.

Hi ha un segon efecte derivat: la feina acabada triga molt a arribar a l'usuari. Una funcionalitat pot estar enllestida al març, integrar-se a develop a l'abril, entrar en una release al maig i publicar-se al juny. Tres mesos de valor aturat en un repositori.

Crítica 3: develop i main se solapen

En projectes amb una sola versió viva i desplegament continu, develop és simplement «main d'aquí a una estona». Dues branques que representen gairebé el mateix generen feina de sincronització sense aportar informació. És la crítica que més se sent, i en aquell context és encertada.

Crítica 4: fricció amb la integració contínua

El CI (lliçó 07-06) vol executar-ho tot contra la línia principal a cada enviament. Amb dues branques permanents i branques de versió efímeres, cal decidir què es prova on, i sol acabar en configuracions complicades de mantenir.

La nota del mateix Vincent Driessen

El març del 2020, deu anys després de l'article original, Driessen va afegir una nota de reflexió a la capçalera del seu propi text. El seu contingut, en resum:

  • El model es va escriure el 2010, quan el món del programari era diferent i el web encara es lliurava per versions.
  • Git Flow continua sent adequat per a programari amb versions explícites, que és per al que es va pensar.
  • Per al desenvolupament web continu, on es desplega constantment i només hi ha una versió en producció, recomana no adoptar Git Flow i fer servir un model més simple, i esmenta explícitament GitHub Flow com a alternativa raonable.
  • I un advertiment general que val per a tot aquest mòdul: no adoptis cap metodologia dogmàticament. Tria segons el teu projecte.

Que l'autor d'un model publiqui una nota així deu anys després és rar i honest, i és la millor manera de tancar aquest apartat. Git Flow no és una mala idea que cal evitar: és una eina específica que es va popularitzar més enllà del seu àmbit.

Errors Habituals i Consells

Error 1: crear una feature/* des de main. Es parteix d'una base sense les funcionalitats ja integrades i s'acumulen conflictes. Neix de develop, sempre.

Error 2: oblidar integrar la release de tornada a develop. Les correccions d'estabilització només queden a main i les errades reapareixen a la versió següent. Comprova-ho amb git log --oneline develop..main.

Error 3: oblidar integrar el hotfix a develop. Problema idèntic, i pitjor, perquè és una errada que el client ja et va reportar un cop.

Error 4: ficar funcionalitats noves en una branca de versió. La branca de versió existeix per estabilitzar. Si hi entra codi nou, no s'estabilitza mai i el cicle s'allarga indefinidament.

Error 5: fusionar amb fast-forward. Es perd l'agrupació de commits per funcionalitat i la possibilitat de revertir-la sencera. --no-ff sempre.

Error 6: etiquetar a develop o a la branca de versió. Les etiquetes van a main, sobre el commit de fusió. Només allà.

Error 7: fer servir etiquetes lleugeres. git tag v2.0.0 crea una referència sense metadades. Fes servir git tag -a.

Error 8: no enviar les etiquetes. git push origin main no se les emporta. --follow-tags.

Error 9: deixar la branca per defecte del repositori a main. Totes les PRs s'obren contra la branca equivocada. A Git Flow, la branca per defecte és develop.

Error 10: adoptar Git Flow perquè és «l'estàndard». Ja no ho és, i probablement mai no ho hauria d'haver estat per a aplicacions web. Adopta'l si el teu producte té versions explícites.

Consell 1: automatitza la comprovació de la doble integració. Una tasca de CI que executi git log --oneline develop..main i falli si hi ha commits sense propagar elimina l'error més car del model.

Consell 2: fes servir el número de versió al nom de la branca. release/2.1.0 diu quina etiqueta produirà.

Consell 3: obre la branca de versió aviat. Allibera develop abans i redueix la pressió sobre l'equip.

Consell 4: actualitza les teves feature/* amb develop sovint. És l'antídot directe contra la crítica 2, i és a la teva mà.

Consell 5: si adoptes git flow, comença per les ordres manuals. Entendre el graf que construeixes val més que estalviar tecles.

Consell 6: branques de suport (suport/1.4) per a versions antigues. El model canònic no les inclou i gairebé tots els productes reals les necessiten.

Exercicis

Exercici 1: muntar el cicle complet

Construeix des de zero un repositori gestor-tasques amb el cicle sencer de Git Flow:

  1. Inicialitza el repositori amb index.html, app.js i README.md, i etiqueta aquell estat com a v1.4.0 a main.
  2. Crea develop des de main.
  3. Desenvolupa feature/exportacio-csv amb dos commits i integra-la a develop amb --no-ff.
  4. Desenvolupa feature/ordre-alfabetic amb un commit i integra-la igual.
  5. Obre release/2.0.0, puja el número de versió al README.md i corregeix una errada.
  6. Tanca la versió: fusiona a main, etiqueta v2.0.0 com a etiqueta anotada, fusiona també a develop i esborra la branca.
  7. Mostra el graf complet i comprova que s'assembla al de l'apartat 3.

Exercici 2: hotfix i verificació de la doble integració

Continuant amb el repositori anterior:

  1. Afegeix una funcionalitat més a develop (simulant la feina de la 2.1).
  2. Obre hotfix/2.0.1 des de main, corregeix una errada i puja la versió de pedaç.
  3. Tanca'l correctament: main amb etiqueta v2.0.1 i develop.
  4. Escriu una ordre que comprovi que no queda res a main sense propagar a develop.
  5. Repeteix l'exercici malament a propòsit (sense integrar a develop) en una còpia del repositori i observa què detecta aquella comprovació.
  6. Arregla la situació amb git cherry-pick.

Exercici 3: mantenir una versió antiga

  1. Crea una branca de suport suport/1.4 des de l'etiqueta v1.4.0.
  2. Porta a aquella branca l'arranjament del hotfix de l'exercici anterior amb git cherry-pick.
  3. Etiqueta el resultat com a v1.4.1.
  4. Llista totes les etiquetes ordenades per versió i comprova amb git describe --contains en quina versió va entrar cada arranjament.
  5. Mostra amb git log --graph --oneline --all --decorate la topologia completa, amb les tres línies vives.

Solucions

Solució 1:

mkdir /tmp/gitflow && cd /tmp/gitflow
git init -qb main
printf '<h1>Gestor de Tasques</h1>\n' > index.html
printf 'const tasques = [];\n' > app.js
printf '# gestor-tasques\n\nVersio: 1.4.0\n' > README.md
git add . && git commit -q -m "Versio inicial de l'aplicacio"
git tag -a v1.4.0 -m "Versio 1.4.0"
git switch -qc develop
# 3. Primera funcionalitat
git switch -qc feature/exportacio-csv
echo "function exportaCSV() { /* ... */ }" >> app.js
git commit -qam "Afegeix l'exportacio a CSV"
echo "function descarrega(nom, dades) { /* ... */ }" >> app.js
git commit -qam "Afegeix la descarrega del fitxer generat"
git switch -q develop
git merge -q --no-ff feature/exportacio-csv -m "Fusiona la branca feature/exportacio-csv"
git branch -qd feature/exportacio-csv
# 4. Segona funcionalitat
git switch -qc feature/ordre-alfabetic
echo "function ordena() { tasques.sort(); }" >> app.js
git commit -qam "Afegeix l'ordenacio alfabetica"
git switch -q develop
git merge -q --no-ff feature/ordre-alfabetic -m "Fusiona la branca feature/ordre-alfabetic"
git branch -qd feature/ordre-alfabetic
# 5. Branca de versio
git switch -qc release/2.0.0
sed -i 's/Versio: 1.4.0/Versio: 2.0.0/' README.md
git commit -qam "Puja la versio a 2.0.0"
echo "// corregit: cometes al titol en exportar" >> app.js
git commit -qam "Corregeix l'escapat de cometes a l'exportacio"
# 6. Tancament amb doble integracio
git switch -q main
git merge -q --no-ff release/2.0.0 -m "Fusiona la branca release/2.0.0"
git tag -a v2.0.0 -m "Versio 2.0.0: exportacio a CSV i ordre alfabetic"
git switch -q develop
git merge -q --no-ff release/2.0.0 -m "Fusiona la branca release/2.0.0 a develop"
git branch -qd release/2.0.0
# 7. El graf
git log --graph --oneline --all --decorate

Solució 2:

# 1. Feina de la 2.1 a develop
git switch -q develop
git switch -qc feature/etiquetes-de-tasca
echo "function posaEtiqueta(id, etiqueta) { /* ... */ }" >> app.js
git commit -qam "Afegeix etiquetes a les tasques"
git switch -q develop
git merge -q --no-ff feature/etiquetes-de-tasca -m "Fusiona la branca feature/etiquetes-de-tasca"
git branch -qd feature/etiquetes-de-tasca
# 2. Hotfix des de main
git switch -q main
git switch -qc hotfix/2.0.1
echo "// corregit: filtrar per usuari a esborraCompletades()" >> app.js
git commit -qam "Corregeix l'esborrat massiu que afectava tasques alienes

El filtre per usuari no s'aplicava a esborraCompletades().
Refs GT-318."
sed -i 's/Versio: 2.0.0/Versio: 2.0.1/' README.md
git commit -qam "Puja la versio a 2.0.1"
# 3. Tancament doble
git switch -q main
git merge -q --no-ff hotfix/2.0.1 -m "Fusiona la branca hotfix/2.0.1"
git tag -a v2.0.1 -m "Versio 2.0.1: corregeix l'esborrat massiu"
git switch -q develop
git merge -q --no-ff hotfix/2.0.1 -m "Fusiona la branca hotfix/2.0.1 a develop"
git branch -qd hotfix/2.0.1
# 4. La comprovacio
git log --oneline develop..main
(buit: tot el de main es a develop)
# 5. La versio incorrecta, en una copia
cp -r /tmp/gitflow /tmp/gitflow-mal && cd /tmp/gitflow-mal
git switch -q main
git switch -qc hotfix/2.0.2
echo "// corregit: data de venciment amb zona horaria" >> app.js
git commit -qam "Corregeix la zona horaria de la data de venciment"
git switch -q main
git merge -q --no-ff hotfix/2.0.2 -m "Fusiona la branca hotfix/2.0.2"
git tag -a v2.0.2 -m "Versio 2.0.2"
git branch -qD hotfix/2.0.2          # sense integrar a develop!
git log --oneline develop..main
d4c1f8a Fusiona la branca hotfix/2.0.2
9b2e7a3 Corregeix la zona horaria de la data de venciment

La comprovació detecta el commit orfe: existeix a main i no a develop. La propera versió reintroduiria l'errada.

# 6. Arranjament
git switch -q develop
git cherry-pick 9b2e7a3
git log --oneline develop..main

Ara només queda el commit de fusió, que és propi de main i no necessita propagar-se.

Solució 3:

cd /tmp/gitflow

# 1. Branca de suport des de l'etiqueta antiga
git switch -qc suport/1.4 v1.4.0

# 2. Portar l'arranjament (el hash del commit de correccio del hotfix)
ARRANJAMENT=$(git log --format=%h --all --grep='esborrat massiu que afectava' -1)
git cherry-pick "$ARRANJAMENT"
# 3. Etiquetar
sed -i 's/Versio: 1.4.0/Versio: 1.4.1/' README.md
git commit -qam "Puja la versio a 1.4.1"
git tag -a v1.4.1 -m "Versio 1.4.1: corregeix l'esborrat massiu"
# 4. Inventari de versions
git tag -l 'v*' --sort=-v:refname
git describe --contains "$ARRANJAMENT"
v2.0.1
v1.4.1
v2.0.0
v1.4.0
# 5. Topologia completa
git log --graph --oneline --all --decorate

Es veuen les tres línies vives: main amb les seves versions etiquetades, develop amb la feina de la 2.1, i suport/1.4 penjant de l'etiqueta antiga.

Conclusió

Git Flow és el model de ramificació més estructurat dels que veurem, i la seva lògica interna és impecable per al problema que resol. L'essencial:

  • Cinc classes de branca: main (només versions publicades i etiquetades), develop (integració del que està acabat), feature/* (de develop a develop), release/* (de develop a main i develop) i hotfix/* (de main a main i develop).
  • develop està integrat, no garantit com a desplegable. L'estabilització passa a la branca de versió, i aquesta és la diferència de fons amb els models que veurem a continuació.
  • La branca de versió és la peça clau: congela l'abast i allibera develop immediatament, permetent estabilitzar sense aturar l'equip.
  • La doble integració de release/* i hotfix/* no és un caprici: sense ella, els arranjaments existeixen a main però no a develop i les errades reapareixen a la versió següent. Automatitza la comprovació amb git log --oneline develop..main.
  • Els hotfix neixen de main perquè cal arreglar el que és en producció, no el que està a mitges en desenvolupament.
  • Les etiquetes anotades van exclusivament sobre els commits de fusió a main, i encaixen de manera natural amb SemVer: release/* puja minor/major, hotfix/* puja patch.
  • git flow és sucre sintàctic, no capacitat nova. Còmode per no oblidar la doble integració, incòmode amb les pull requests.
  • Encaixa amb programari de versions explícites, diverses versions mantingudes, lliuraments planificats i QA manual: producte instal·lable, mòbil, biblioteques, encastats.
  • No encaixa amb web de desplegament continu i una sola versió viva, i així ho va reconèixer el mateix Driessen a la seva nota del 2020, on recomana models més simples per a aquell cas.

Aquella nota és justament el pont cap al que ve. Si el teu producte és una aplicació web que es desplega diverses vegades al dia, de debò calen dues branques permanents, branques de versió i una fase d'estabilització? La resposta del model que veurem ara és un no rotund: una sola branca de vida llarga, sempre desplegable, i branques curtes que hi entren per pull request. Això és el contingut de la lliçó 07-04: GitHub Flow.

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