1.4 La intención es lo que cuenta

El libro se puede descargar aquí

1.4.1 Ejemplo 4 - conflicto sobre nuestro adorado script

Listing 1.68:Ejemplo 4
1#!/usr/bin/python 
2 
3import sys 
4 
5colors = {"black": "black mirror", 
6          "white": "white noise", 
7          "blue": "blue sky"} 
8 
9def getPhrase(color): 
10<<<<<<< HEAD 
11    phrase = "%s: %s" % (color, colors[color]) 
12    return phrase 
13||||||| c8bf13a 
14    phrase = colors[color] 
15    return phrase 
16======= 
17    if color in colors: 
18        phrase = colors[color].upper() 
19        return phrase 
20    else: 
21        sys.stderr.write("%s is not a known color\n" % color) 
22        sys.exit(1) 
23>>>>>>> example4/branchB 
24 
25print(getPhrase(sys.argv[1]))

Se podría resolver como lo hemos hecho hasta ahora. Se comienza a trabajar en el UB24 :

Listing 1.69:Ejemplo 4 - Paso 1 - UB
10<<<<<<< HEAD 
11    phrase = "%s: %s" % (color, colors[color]) 
12    return phrase 
13||||||| c8bf13a

Ahora consideramos el dML:

Listing 1.70:Ejemplo 4 - Paso 2 - dML
13||||||| c8bf13a 
14    phrase = colors[color] 
15    return phrase 
16======= 
17    if color in colors: 
18        phrase = colors[color].upper() 
19        return phrase 
20    else: 
21        sys.stderr.write("%s is not a known color\n" % color) 
22        sys.exit(1) 
23>>>>>>> example4/branchB

dML: Hay una nueva condición que verifica que el color esté definido (línea 17). Si no existe, cae en el bloque else (líneas 20-22). Las líneas preexistentes se colocaron dentro del condicional y se ajustó su indentación por esa razón (líneas 18-19). Primero, copiemos esas líneas desde el LB hacia el UB.

Listing 1.71:Ejemplo 4 - Paso 3 - Copiar desde el LB
10<<<<<<< HEAD 
11    if color in colors: 
12        phrase = colors[color].upper() 
13        return phrase 
14    else: 
15        sys.stderr.write("%s is not a known color\n" % color) 
16        sys.exit(1) 
17||||||| c8bf13a

Casi lo tenemos. Pero hay un problema: Como copiamos el contenido verbatim, perdimos la línea del UB donde se estaba cambiando la frase para incluir el color original. Miren el UB antes de comenzar a resolver de nuevo (línea 11):

Listing 1.72:Ejemplo 4 - Paso 1 - UB
10<<<<<<< HEAD 
11    phrase = "%s: %s" % (color, colors[color]) 
12    return phrase 
13||||||| c8bf13a

Ok, entonces debemos poder reemplazar la línea donde colocamos el valor desde el diccionario y con eso estaría bien: 25

Listing 1.73:Ejemplo 4 - Paso 4 - Editar el UB
10<<<<<<< HEAD 
11    if color in colors: 
12        phrase = "%s: %s" % (color, colors[color]) 
13        return phrase 
14    else: 
15        sys.stderr.write("%s is not a known color\n" % color) 
16        sys.exit(1) 
17||||||| c8bf13a

Eso tampoco es correcto. Ahora se pierde la llamada a upper() que viene del LB. Así que no podemos copiar cambios verbatim de un bloque al otro? Todo depende de lo que se traten los cambios. En este caso la línea está recibiendo cambios por las dos ramas así que debemos considerar la intención de ambas, no los cambios literales.

Comencemos a resolver el conflicto desde el principio, en el UB:

Listing 1.74:Ejemplo 4 - Paso 1 - UB
10<<<<<<< HEAD 
11    phrase = "%s: %s" % (color, colors[color]) 
12    return phrase 
13||||||| c8bf13a

El dML (paso 2) no ha cambiado. Una nueva condición se agregó y la copiamos en el paso 3:

Listing 1.75:Ejemplo 4 - Paso 3 - Conditional
10<<<<<<< HEAD 
11    if color in colors: 
12    phrase = "%s: %s" % (color, colors[color]) 
13    return phrase 
14||||||| c8bf13a

Necesitamos ajustar la indentación de las lineas como se hizo en la otra rama:

Listing 1.76:Ejemplo 4 - Paso 4 - Adjustar indentación
10<<<<<<< HEAD 
11    if color in colors: 
12        phrase = "%s: %s" % (color, colors[color]) 
13        return phrase 
14||||||| c8bf13a

Agregamos la llamada a upper():

Listing 1.77:Ejemplo 4 - Paso 5 - llamada a upper()
10<<<<<<< HEAD 
11    if color in colors: 
12        phrase = "%s: %s" % (color, colors[color].upper()) 
13        return phrase 
14||||||| c8bf13a

Agregamos el bloque else:

Listing 1.78:Ejemplo 4 - Paso 6 - bloque else
10<<<<<<< HEAD 
11    if color in colors: 
12        phrase = "%s: %s" % (color, colors[color].upper()) 
13        return phrase 
14    else: 
15        sys.stderr.write("%s is not a known color\n" % color) 
16        sys.exit(1) 
17||||||| c8bf13a

Y ahora llegamos a la solución del conflicto. Remuevan las otras partes del conflicto y los marcadores:

Listing 1.79:Ejemplo 4 - final
1#!/usr/bin/python 
2 
3import sys 
4 
5colors = {"black": "black mirror", 
6          "white": "white noise", 
7          "blue": "blue sky"} 
8 
9def getPhrase(color): 
10    if color in colors: 
11        phrase = "%s: %s" % (color, colors[color].upper()) 
12        return phrase 
13    else: 
14        sys.stderr.write("%s is not a known color\n" % color) 
15        sys.exit(1) 
16 
17print(getPhrase(sys.argv[1]))

Pero entonces, si no podemos copiar código de una rama a la otra, como hacemos el trabajo? El truco es replicar los cambios que fueron incluidos en el dML y colocarlos en el UB, no copiar los cambios.

Este trabajo donde se debe analizar cuidadosamente lo que ha cambiado (palabra por palabra, espacio por espacio, tab a tab, paréntesis a paréntesis, condicional a condicional) debe ser hecho en cada uno de los conflictos a los que se enfrenten. Me encantaría darles un truco para pode hacer este trabajo más sencillo... pero no lo hay. Una herramienta valiosa que podrían utilizar bajo ciertas circunstancias es usar git diff –color-words para comparar el ancestro común con las ramas... o incluso las ramas entre ellas: 26

Figure 1.1:Diferencias introducidas por la rama branchA
PIC
Figure 1.2:Diferencias introducidas por la rama branchB
PIC

Cuando las personas deciden no hacer este trabajo exhaustivamente, fácilmente se escapan detalles de las ramas involucradas (o se copia cambios verbatim borrando otros cambios) y eso es lo que eventualmente podría reventar tiempo después, algunas veces de forma GRANDE.... ESPECTACULAR... FULGURANTE.... en producción. Ciertamente no el mejor sitio para enterarse de que no se trajo un cambio en un merge hace algunas semanas o meses.

Si se agrega código a una rama, probablemente debería quedar en el código resultante, justo como hicimos con la sección else 27. Y el código borrado es un caso especial que debe ser analizado cuidadosamente por lo que estaré abordándolo más adelante.

1.4.2 Ejercicios

Ejercicio 4 - un conflicto en git

Del repo de git, hagan checkout de la revisión d9d65e9f6a y hagan merge de b57e8119e6. 28 La solución está aquí.

Ejercicio 5 - otro conflicto en git

Del repo de git, hagan checkout de la revisión cf054f817a y hagan merge de caf388caa1. 29 La solution está aquí.

Copyright 2020 Edmundo Carmona Antoranz