Tutorial de git/Treball amb branques

El poder treballar amb branques és una de les coses que fa que el git sigui diferent de la resta de controls de versions. Crear branques amb git és molt fàcil i barat, i moure's entre elles molt senzill. El fet que tingui una bona resolució de conflictes també fa que treballar amb branques en el git sigui un plaer.

En aquest apartat també suposarem que el treball és força lineal. Potser tindrem més d'un front de treball (penso en 2 o 3 com a màxim), i els fronts avançaran bastant paraŀlelament i coordinada.

Abans de començar a explicar com fer anar les branques amb el git podem discutir quan cal crear una branca i quan no. Contestar a la pregunta de quan no crear una branca sembla el més fàcil; quan tinguis molt clar que has de fer i ho puguis fer amb els ulls tancats no cal crear una branca. Contestar a la pregunta de quan crear una branca és una cosa bàsicament subjectiva, però hi ha un parell de casos on fer servir branques facilita les coses. Aquests dos casos són:

  • Per fer proves. Quan tens una idea al cap i no saps si funcionarà
  • Per afegir una funcionalitat que preveus difícil

En aquests dos casos (especialment en el primer) és fàcil que tot el que has fet no serveixi per res. Tenir-ho en una branca et permet anar treballant en paraŀlel amb funcionalitats que saps que són fàcils d'implementar i necessàries; i també et permet que al final si la cosa ha anat bé integrar les funcionalitats de la branca amb la branca principal de desenvolupament, o si ha anat malament esborrar la branca i oblidar-te'n.

Un cop ja sabem la utilitat bàsica de les branques passarem a explicar com treballar amb branques.

Crear una branca modifica

Recordem que igual que amb les etiquetes, les branques no poden fer servir qualsevol caràcter.

La comanda per crear una branca és git branch nom_de_la_branca. Amb aquesta comanda creem una branca, però git no ens torna massa informació. De fet ha creat la branca... Però com ho sabem? Doncs amb la comanda git branch podem veure quines branques hi ha i en quina estem. La que està marcada amb un asterisc és en la que ens trobem.

Moure's entre branques modifica

Ara que ja hem creat una branca hem d'aprendre a moure'ns (sinó ja veus de què serveix...). Per tal de moure'ns entre branques la comanda que fem servir és git checkout nom_de_la_branca. Això ens canvia de branca. Ho podem comprovar amb un git branch.

Ara deveu pensar que això de fer un git branch nom; git checkout nom no és massa productiu... I amb tota la raó. És per això que el git et permet crear una branca i canviar a ella a la vegada amb la comanda
git checkout -b nova_branca

Una cosa que cal tenir en compte és que abans de canviar de branca no hi ha d'haver cap canvi a la branca de treball (quan fem un git status ha de dir-nos: nothing to commit (working directory clean)). Si hi ha alguna cosa no ens deixarà canviar.

Ajuntar dues branques modifica

Hi ha tres maneres d'ajuntar dues branques, però per aquest tutorial només explicarem la més bàsica. Les altres són interessants, val la pena fer-hi una ullada.

Quan l'objectiu de la branca s'ha complert i ha sortit satisfactòriament el que hem de fer és ajuntar la branca de la nova funcionalitat amb la branca principal per poder tenir la nova funcionalitat.

Per fer això primer de tot ens posem a la branca principal (on volem que s'ajunti) git checkout master i aleshores ajuntem les dues branques amb git merge nova_branca.

Si no hi ha cap conflicte les branques s'ajuntaran sense més problema. Si hi ha algun conflicte en el proper subapartat explico com resoldre'l.

Resoldre conflictes modifica

Quan en ajuntar dues branques hi ha algun problema perquè s'ha trobat algun conflicte, s'ha de resoldre el conflicte.

Hi ha una manera manual de resoldre'l o es pot fer servir un programa.

La manera en la que indica els conflictes git és de la següent:

  fitxer
  <<<< HEAD:fitxer
  continguts
  del 
  fitxer
  a la branca on ets
  ===================
  continguts
  del 
  fitxer
  a la branca que ajuntes
  >>>> nova_branca:fitxer

El que has de fer és treure la part que no t'interessa i deixar la que t'interessa. Quan hagis resolt tots els conflictes afegeixes els canvis i fas un commit

Per conflictes senzills la manera manual va molt bé, però per conflictes més complicats és millor fer servir un programa. La comanda git mergetool ens ofereix diferents programes (que ja hem de tenir instaŀlats) per resoldre els conflictes.

Aquesta manera fa més visual la resolució de conflictes.

Esborrar una branca modifica

Un cop hem ajuntat dues branques tota la història de la branca que s'ha ajuntat queda reflectida a l'altra branca. És per aquest motiu que moltes vegades ja podem esborrar la branca.

Per tal d'esborrar una branca la comanda és git branch -d nom_de_la_branca. Aquesta comanda permet esborrar branques que s'han ajuntat a d'altres branques i que per tant la informació que conté no es perdrà.

Si estem treballant en una idea i veiem que no te futur, i volem esborrar la branca, hem de fer servir el paràmetre -D. Per tant per esborrar una branca que no ha estat ajuntada en cap altra farem servir la comanda git branch -D nom_branca

En aquest punt ja som capaços de fer servir el git d'una manera força completa i per treballar normal ja tenim suficient.

Canviar el nom d'una branca modifica

Hi ha vegades en que ens interessa canviar el nom d'una branca. La comanda per fer-ho és molt senzilla

 git branch -m nom_antic nom_nou

Fer referència a una branca després d'ajuntar-les modifica

Després d'ajuntar dues branques un commit té dos pares. La manera més senzilla de referenciar-les és fer servir el ID. Però tal com hem dit a l'apartat #Mirar la història del repositori hi ha una altra manera de fer-ne referència.

El accent circumflex (^) recordem que hem dit que feia referència al pare d'un commit. Però quan acabem d'ajuntar dues branques hi ha més d'un pare. Per això l'accent circumflex s'acostuma a fer servir seguit d'un número per tal de fer referència a un pare concret.

Imaginem que ens trobem en la següent situació:

X -- X -- X -- A -- 0
X -- X -- X -- B --´

Acabem d'ajuntar dues branques i ens trobem en el commit 0. Si volem informació a partir del commit A podem fer la comanda git log HEAD^... Si en canvi ho volem des del commit B podem fer servir la comanda git log HEAD^2..

L'accent circumflex es pot combinar amb la titlla. Per exemple imaginem la situació:

X -- X -- X -- A -- X -- X -- 0
X -- X -- X -- B --´

Si ara ens trobem en el commit 0 i volem veure la informació a partir del commit A podem fer: git log HEAD~2^. Si en canvi ho volem saber des del commit B haurem de fer: git log HEAD~2^2

Crear una branca a partir d'uns quants commits modifica

Moltes vegades comencem amb una funcionalitat en la branca principal ja que pensem que serà fàcil de fer, però quan estem a mitges amb 3 o 4 commits fets ens adonem que no és tan fàcil i pensem per què no hem creat una branca.

Doncs això té solució. El que hem de fer és crear una branca en el punt on ens trobem per la funcionalitat en la que estem treballant, i llavors esborrem els commits d'aquesta funcionalitat en la branca principal.

Imaginem que la nostra branca principal la tenim de la següent manera:

  X -- X -- A -- 1 -- 2 -- 3

On A és l'últim commit de les funcionalitats que funcionen i els commits 1 2 3 són els de la funcionalitat que imaginàvem fàcil i que hem decidit que es mereix una branca. Doncs el que fem és git branch nova_funcionalitat i a continuació git reset --hard HEAD~3 i ens queda com:

X -- X -- A
           `-- 1 -- 2 -- 3

I ara ja podem fer un checkout a la nova branca o afegir una nova funcionalitat (realment fàcil) a la branca principal.