Fusiones conflictivas

Cuando hacemos fusiones más avanzadas en Git corremos el riesgo de que se desate un conflicto. Hoy estudiamos qué ocurre si hacemos modificaciones al mismo archivo en varias ramas.

Cuando trabajamos con Git, las fusiones suelen ser sencillas si los cambios se hacen en archivos diferentes o en partes distintas del código. Sin embargo, la cosa se complica cuando modificamos el mismo archivo en distintas ramas. Git, por suerte, es bastante inteligente y realiza las fusiones línea a línea, lo que le permite integrar cambios en un mismo archivo siempre que no afecten a las mismas líneas.

Para ilustrar esto, imaginemos que tenemos una rama principal, master, y creamos una rama nueva llamada feature-comercial-text para añadir un texto comercial que nos ayude a incrementar las ventas. En esta rama escribimos un mensaje sobre la tradición de la empresa en la venta de jarrones chinos y la satisfacción de los clientes. Mientras tanto, el cliente nos pide cambiar el mensaje superior de la pantalla para que sea más enfático, así que creamos otra rama llamada fix-texto-superior desde master y modificamos esa parte del texto.

Cuando integramos primero la rama fix-texto-superior en master, Git lo resuelve fácilmente con un fast-forward porque master no había cambiado antes. Luego, al integrar feature-comercial-text, Git utiliza un merge recursivo, ya que ambos cambios afectan al mismo archivo pero en líneas diferentes, por lo que no hay conflicto.

Pero, ¿qué pasa si modificamos la misma línea en dos ramas diferentes? Para verlo, creamos una rama fix-octubre donde cambiamos la fecha de apertura a 15 de octubre y otra rama fix-gramatica donde corregimos la gramática de la frase que anuncia la inauguración del sitio web. Ambas modificaciones afectan a la misma línea del archivo index.html.

Al intentar fusionar estas dos ramas en master, Git detecta un conflicto porque no puede decidir automáticamente cuál de las dos versiones es la correcta. En este caso, Git marca el archivo en conflicto insertando delimitadores especiales que muestran ambas versiones del texto:

<<<<<<< HEAD
Estamos a punto de inaugurar el sitio web el 1 de octubre.
=======
Vamos a inaugurar el sitio web el 1 de octubre.
>>>>>>> fix-gramatica

Aquí, HEAD representa la versión actual en master y fix-gramatica la versión de la rama que intentamos fusionar. Nuestra tarea es elegir qué texto queremos conservar, o incluso combinar ambos, y eliminar estos símbolos para dejar el archivo limpio.

Por ejemplo, podemos decidir quedarnos con una frase que combine lo mejor de ambas versiones:

Vamos a inaugurar el sitio web el 1 de octubre.

Después de resolver el conflicto, añadimos el archivo con git add index.html y hacemos el commit para finalizar la fusión. Git reconoce que el conflicto ha sido resuelto y completa el merge.

Aunque los conflictos pueden parecer intimidantes al principio, en realidad son una oportunidad para revisar y decidir manualmente cómo debe quedar el código cuando dos cambios chocan. Es raro que ocurran en código muy serio, ya que normalmente se procura que dos personas no trabajen en la misma línea simultáneamente, pero cuando suceden, saber cómo resolverlos es fundamental para mantener un flujo de trabajo ordenado y efectivo.

En próximos ejemplos podemos explorar conflictos más complejos, pero por ahora, entender cómo Git maneja fusiones línea a línea y cómo resolver conflictos básicos nos prepara para trabajar con ramas limpias y sincronizadas sin miedo a perder cambios importantes.

Lista de reproducción
  1. 1
    ¿Qué es Git?
    4 minutos
  2. 2
    Cómo instalar Git
    9 minutos
  3. 3
    Creando tu primer commit
    9 minutos
  4. 4
    Qué es el staging area
    10 minutos
  5. 5
    Cómo deshacer modificaciones de archivos
    7 minutos
  6. 6
    Cómo deshacer un commit con reset
    7 minutos
  7. 7
    Cómo revertir un commit con revert
    7 minutos
  8. 8
    Introducción a las ramas
    6 minutos
  9. 9
    Cómo crear y modificar ramas
    6 minutos
  10. 10
    Commits bajo el workflow Feature Branch
    6 minutos
  11. 11
    Cómo fusionar ramas con merge
    6 minutos
  12. 12
    Fusiones conflictivas
    9 minutos
  13. 13
    Cómo construir alias
    7 minutos
  14. 14
    Más sobre conflictos
    9 minutos
  15. 15
    Etiquetas
    7 minutos
  16. 16
    Tags anotados
    9 minutos
  17. 17
    git stash: esconder cambios
    6 minutos
  18. 18
    Introducción a remotos
    5 minutos
  19. 19
    Pusheando a un remoto
    6 minutos
  20. 20
    Clonando y haciendo pull
    6 minutos
  21. 21
    Fetch y pull rebases
    8 minutos
  22. 22
    Rebase
    7 minutos
  23. 23
    Rebase interactivo
    6 minutos
  24. 24
    Master, main y otros nombres de rama
    9 minutos
  25. 25
    git switch
    9 minutos
  26. 26
    git-restore
    10 minutos
  27. 27
    git-grep
    11 minutos
  28. 28
    Gitignore
    11 minutos
  29. 29
    El flag --patch
    9 minutos
  30. 30
    git-apply y parches en bruto (advanced)
    9 minutos
  31. 31
    Merge octopus (advanced)
    9 minutos
  32. 32
    Conventional commits
    12 minutos
  33. 33
    Merge and squash (GitLab / GitHub...)
    6 minutos
  34. 34
    git merge --squash
    7 minutos
  35. 35
    git-bisect
    8 minutos
  36. 36
    git-blame
    6 minutos
  37. 37
    git-reflog
    10 minutos
  38. 38
    Git para la Bash
    11 minutos
  39. 39
    Submódulos (parte 1)
    7 minutos
  40. 40
    Submódulos (parte 2)
    10 minutos
  41. 41
    Otros clientes Git (último episodio)
    9 minutos