Taula de continguts

Git: Exemple de conflicte

Els conflictes de versions es donen quan dos desenvolupadors han modificat la mateixa línia (o línies) de codi. Forçarem un senzill exemple de conflicte que Git detectarà, simulant el treball de dos developers en branques diferents. Partirem d'un simple arxiu circ.py del qual derivarem 2 branques i, finalment, les fusionarem, trobant el conflicte.

, , , , , , , , , , , , , , , , , , , , ,

En aquest exemple es fa tot a la mateixa màquina i carpeta per forçar un conflicte. La situació «real» seria que dos desenvolupadors estarien en màquines diferents i el conflicte arribaria quan incorporessin els canvis de l'altre mitjançant un fetch.

Codi

Dos desenvolupadors volen treballar amb el següent codi i parteixen d'aquesta primera versió. Tots dos tindran la mateixa pensada, millorar la precisió del valor PI, però un hi afegirà 4 decimals i l'altre 5, resultant en un conflicte de codi.

circ.py
#!/usr/bin/env python3
radi = input("Radi de la circumferència? ")
PI = 3.14
perimetre = 2*PI*float(radi)
print("El perímetre de la circumferència de radi {} és {}".format(radi,perimetre))


Branques

Històricament, al crear un repositori Git es crea una branca per defecte anomenada «master». Temps després s'ha estimat que la referència «master/slave» que se'n dedueix no era adequada ja que recorda el passat esclavista i uns valors dels quals es vol passar pàgina. Per això en la majoria de tutorials de Git sempre es sol canviar el nom de la branca principal a «main».

Per tal de treballar en paral·lel, els dos desenvolupadors crearan 2 branques iguals a partir d'aquest codi (a part de la main). Amb les següents instruccions es crearan 2 branques iguals a partir d'aquest codi:

$ git init
$ git branch -M main    # la branca principal l'anomenem main en lloc de master
$ git add .                   # s'afegeixen tots els arxius i carpetes del directori actual (./)
$ git commit -am "primer commit"
$ git branch dev_a       # simulem developer a
$ git branch dev_b       # simulem developer b

El primer developer treballa a la branca dev_a:

$ git checkout dev_a

I aplica canvis per fer el valor de PI mes exacte PI = 3.1416 a l'arxiu circ.py.

$ git commit -am "millora de PI"

En canvi, l'altre desenvolupador treballa a la branca dev_b:

$ git checkout dev_b

En extreure la branca dev_b amb checkout es pot observar que l'arxiu és l'original i PI torna al valor inicial. Canvia PI per PI = 3.14159 (5 decimals de precisió).

$ git commit -am "PI mes exacte"

Per fer el merge (integració de les dues branques) cal situar-se a la branca destí (en aquest cas main) amb la instrucció checkout i incorporar les branques (primer dev_a i després dev_b):

Git funciona per línies. Les insercions i eliminacions detectades fan referència al nombre de línies trobades amb canvis. 1 inserció (+) i 1 eliminació (-) és el que detecta quan modifiquem una sola línia.

$ git checkout main
$ git merge dev_a
 1 file changed, 1 insertion(+), 1 deletion(-)


Conflicte

La fusió de la branca dev_a sobre main no ha donat errors. Procedim amb la fusió de la segona branca:

$ git merge dev_b
 S'està autofusionant circ.py 
 CONFLICTE (contingut): Conflicte de fusió en circ.py
 La fusió automàtica ha fallat; arregleu els conflictes i després cometeu el resultat.

A l'arxiu de codi, Git ha introduït cert text (<<<< ==== >>>>) per ressaltar el conflicte detectat, ja que els dos developers han tocat la mateixa línia:

#!/usr/bin/env python3
radi = input("Radi de la circumferència? ")
<<<<<<< HEAD
PI = 3.1416
=======
PI = 3.14159
>>>>>>> dev_b
perimetre = 2*PI*float(radi)
print("El perímetre de la circumferència de radi {} és {}".format(radi,perimetre))


Resolució

El darrer desenvolupador es trobarà el conflicte en fer el merge de l'altra branca, i haurà de decidir si posa un valor o un altre, eliminar les línies que ressalten el conflicte i tornar a fer un commit amb la correcció sobre la branca main. En aquest cas, el darrer desenvolupador opta per emprar el valor de PI amb més decimals de precisió:

#!/usr/bin/env python3
radi = input("Radi de la circumferència? ")
PI = 3.14159
perimetre = 2*PI*float(radi)
print("El perímetre de la circumferència de radi {} és {}".format(radi,perimetre))

I guardar el codi resultant amb un commit que tancarà la fusió que teníem pendent de resoldre:

$ git commit -am "arranjament PI més precís"