Capítulo 7: Merge y resolución de conflictos¶
Git se vuelve realmente interesante cuando empiezas a combinar ramas que han evolucionado en paralelo. En muchos casos, Git puede integrar automáticamente los cambios. Pero cuando dos ramas modifican la misma parte del mismo archivo de formas incompatibles, aparece un conflicto de Merge. Lejos de ser un error catastrófico, un conflicto es la forma que tiene Git de pedir tu ayuda para decidir qué versión debe ganar.[web:128][web:131]
En este capítulo aprenderás a provocar conflictos de forma controlada sobre el proyecto del libro, interpretar los mensajes de Git, resolver conflictos manualmente y usar Visual Studio Code como herramienta visual para simplificar el proceso. La meta es clara: perder el miedo a los conflictos y entenderlos como parte natural del trabajo diario de cualquier desarrollador.
7.1 ¿Qué es un conflicto de Merge?¶
La documentación y los tutoriales de Git describen el conflicto de Merge como una situación en la que Git no puede combinar automáticamente las diferencias entre dos commits o ramas.[web:128] Eso ocurre cuando los cambios son incompatibles o se superponen en las mismas líneas.
Por qué aparecen¶
Imagina dos versiones de tu sitio web personal:
- En la rama
seccion-recursos, cambias el título principal deindex.htmla “Recursos para tu aprendizaje”. - En la rama
pagina-contacto, cambias ese mismo título a “Bienvenido a mi sitio personal”.
Ahora intentas hacer un merge de pagina-contacto en main, que ya recibió los cambios de seccion-recursos. Git se encuentra con dos versiones distintas del mismo bloque de texto y no puede decidir solo cuál conservar.
En ese punto, aparece el conflicto: Git detecta diferencias incompatibles en las mismas líneas y detiene el merge para pedir tu intervención.[web:128][web:131]
Cuándo ocurren¶
Los conflictos pueden aparecer en varias operaciones:
- al hacer
git mergeentre dos ramas; - al hacer
git pullcuando tu rama local tiene cambios que chocan con commits nuevos del remoto; - en otros flujos como
rebase, aunque aquí nos centraremos en merges.
En todos los casos, la causa es la misma: Git no puede decidir cómo combinar los cambios en algunas partes del código.
Por qué Git necesita tu intervención¶
Git es muy bueno para combinar cambios cuando:
- se añaden nuevas líneas en lugares distintos;
- se modifican partes separadas del archivo;
- se alteran archivos diferentes.
Pero cuando las mismas líneas se cambian de forma incompatible, Git no sabe cuál es la intención final. Podría adivinar, pero eso sería peligroso. La respuesta profesional es simple: Git protege tu trabajo y te obliga a revisar manualmente esas secciones.[web:128][web:131]
Ejemplo cotidiano¶
Piensa en un documento de clase que compartes con otra persona:
- tú cambias el título a “Guía de Git y GitHub”.
- otra persona cambia el mismo título a “Curso práctico de control de versiones”.
Si alguien intenta combinar ambos documentos automáticamente, el sistema no puede dejar dos títulos en la misma línea sin decidir cuál gana. Necesita que alguien mire los cambios y diga cómo debe quedar finalmente.
Nota
Un conflicto no significa que Git “se rompió”, sino que encontró cambios que no puede combinar automáticamente sin arriesgar el contenido.
Breve conclusión: un conflicto de Merge aparece cuando dos ramas modifican las mismas líneas de forma incompatible y Git necesita que el desarrollador decida qué versión conservar.
7.2 Provocando nuestro primer conflicto¶
Para aprender a resolver conflictos, primero necesitamos provocarlos de forma controlada sobre el proyecto del libro. Utilizaremos el sitio web personal y dos ramas que modifican la misma sección de index.html.
Escenario didáctico¶
Partimos de:
- Rama principal:
maincon el sitio estable. - Dos nuevas ramas:
pagina-contactoytexto-alternativo, por ejemplo.
Nuestro objetivo es que ambas ramas cambien la misma línea de index.html con textos distintos.
Paso 1: preparar el estado inicial¶
- Asegúrate de estar en
mainy con el repositorio limpio:
- Verifica que
index.htmltiene un título inicial, por ejemplo:
Paso 2: crear la primera rama y modificar el archivo¶
- Crea y cambia a la rama
pagina-contacto:
- Modifica
index.htmlcambiando el título a:
- Haz un commit:
Paso 3: volver a main y crear la segunda rama¶
- Vuelve a
main:
- Crea y cambia a la rama
texto-alternativo:
- Modifica la misma línea de
index.html, pero con otra versión:
- Haz otro commit:
Ahora tenemos:
pagina-contactocon un título;texto-alternativocon otro título diferente;- ambas ramas nacieron de
mainpero divergen en la misma línea.
Paso 4: generar el conflicto¶
- Vuelve a
main:
- Haz merge primero de una de las ramas, por ejemplo
pagina-contacto:
Si el merge es exitoso, main ahora contiene el título de pagina-contacto.
- Intenta ahora hacer merge de
texto-alternativoenmain:
En este punto, Git debería generar un conflicto, porque texto-alternativo quiere cambiar la misma línea que ya cambió pagina-contacto.[web:128]
Diagrama: dos ramas modificando el mismo archivo¶
flowchart TD
A[main con título original] --> B[Crear rama pagina-contacto]
A --> C[Crear rama texto-alternativo]
B --> D[Modificar título en pagina-contacto]
C --> E[Modificar título en texto-alternativo]
D --> F[Merge pagina-contacto a main]
F --> G[Intentar merge texto-alternativo a main]
G --> H[Conflicto en index.html]
Este diagrama ilustra que el conflicto es consecuencia directa de cambios divergentes en la misma sección del archivo.
Error común
Pensar que los conflictos “aparecen de la nada”. En realidad, son producto de cambios reales que has hecho en ramas distintas sobre el mismo contenido.
Breve conclusión: provocar un conflicto consiste en crear dos ramas que modifiquen la misma parte del mismo archivo y luego intentar fusionarlas en una rama común.
7.3 Comprendiendo el mensaje de Git¶
Cuando ocurre un conflicto, Git detiene el merge y muestra un mensaje en la terminal. Entender ese mensaje es el primer paso para resolver el problema con calma.
Mensaje de error típico¶
Tras el comando:
Podrías ver algo similar a:
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
Este mensaje indica:[web:128][web:131]
- que Git intentó hacer merge automático (
Auto-merging index.html); - que encontró un conflicto de contenido en
index.html(CONFLICT (content)); - que el merge automático falló y debes arreglar los conflictos y luego hacer un commit.
Archivos afectados¶
Si ejecutas:
Verás algo parecido a:
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
Esto te dice:[web:136]
- estás en la rama
main; - hay rutas no fusionadas (
unmerged paths); index.htmlfue modificado en ambas ramas (both modified).
Estado del repositorio¶
Mientras el conflicto no se resuelva:
- el merge está “en pausa”;
- no puedes hacer un nuevo merge sobre la misma rama;
- el repositorio permanece en un estado bloqueado para esa operación.
Tienes dos opciones:
- resolver el conflicto y completar el merge;
- abortar el merge si decides no seguir adelante.
La documentación y muchos tutoriales recuerdan que puedes usar git merge --abort para volver al estado anterior al merge si aún no tocaste los archivos.[web:136]
Nota
El mensaje “Automatic merge failed; fix conflicts and then commit the result” es la forma estándar de Git de decirte: “he hecho todo lo que podía, ahora necesito tu ayuda”.[web:128]
Breve conclusión: el mensaje de Git te indica qué archivos tienen conflictos, qué tipo de conflicto es y qué pasos generales debes seguir: solucionar los conflictos y luego hacer un nuevo commit.
7.4 Analizando un archivo en conflicto¶
Para ayudarte a resolver conflictos, Git inserta marcadores especiales en los archivos afectados. GitHub y otros recursos documentan estos marcadores como <<<<<<<, ======= y >>>>>>>, explicando que delimitan los bloques de cambios en conflicto.[web:141][web:127]
Estructura básica de un conflicto¶
Cuando abres index.html tras el conflicto, verás algo como:
<h1>
<<<<<<< HEAD
Bienvenido a mi sitio web personal - Contáctame para aprender Git
=======
Tu espacio personal para aprender Git y GitHub paso a paso
>>>>>>> texto-alternativo
</h1>
Esta estructura tiene tres partes principales:[web:141]
-
<<<<<<< HEAD -
indica el inicio del bloque de conflicto;
-
el contenido que sigue pertenece a la rama actual (en este caso,
main) o al commit donde estás intentando integrar los cambios.[web:141] -
======= -
es el separador entre tu versión y la versión de la rama que estás fusionando;
-
marca el punto de comparación entre ambas.[web:141]
-
>>>>>>> texto-alternativo -
indica el final del bloque de conflicto;
- menciona la rama desde la cual vienen los cambios en conflicto (
texto-alternativo).[web:141]
Cómo identificar los cambios¶
En nuestro ejemplo:
- El bloque entre
<<<<<<< HEADy=======corresponde al título tal como está enmaindespués de integrarpagina-contacto. - El bloque entre
=======y>>>>>>> texto-alternativocorresponde a la versión del título que propone la ramatexto-alternativo.
Tu tarea es decidir cómo debe quedar el título final.
Decidir qué conservar¶
Tienes varias opciones conceptuales:
- Conservar solo la versión de
HEAD(la rama actual). - Conservar solo la versión de la rama
texto-alternativo. - Fusionar ambas versiones en un nuevo texto que incorpore lo mejor de cada una.
Lo importante es que no puedes dejar los marcadores (<<<<<<<, =======, >>>>>>>) en el archivo cuando termines. Deben eliminarse después de decidir el contenido correcto.[web:127]
[Ilustración: archivo HTML abierto en un editor, mostrando claramente los marcadores de conflicto <<<<<<< HEAD, ======= y >>>>>>> texto-alternativo, con resaltado visual sobre cada bloque para identificar “mi versión”, “su versión” y el área que debe decidirse]
Curiosidad
Git no intenta adivinar tu intención. Solo marca los bloques en conflicto y te muestra de dónde viene cada cambio. Tú decides el resultado final.[web:141]
Breve conclusión: los marcadores <<<<<<<, ======= y >>>>>>> delimitan las versiones en conflicto dentro de un archivo. Entender qué bloque representa cada rama es clave para resolver el conflicto.
7.5 Resolviendo conflictos manualmente¶
Resolver un conflicto manualmente significa editar el archivo, decidir el contenido final, eliminar los marcadores y luego decirle a Git que el conflicto quedó resuelto.
Procedimiento completo¶
Tomemos el conflicto de index.html como ejemplo.
- Abre el archivo en tu editor (puede ser VS Code o cualquier otro).
- Localiza el bloque de conflicto delimitado por
<<<<<<<,=======y>>>>>>>. - Decide qué texto debe quedar.
- Edita el contenido para que el bloque completo se convierta en la versión final que quieras.
- Elimina los marcadores de conflicto.
- Guarda el archivo.
- Prepara el archivo con
git add. - Finaliza el merge con un nuevo
git commit.
Ejemplo concreto de resolución¶
Supongamos que quieres fusionar ambas ideas en un solo título:
Antes (con conflicto):
<h1>
<<<<<<< HEAD
Bienvenido a mi sitio web personal - Contáctame para aprender Git
=======
Tu espacio personal para aprender Git y GitHub paso a paso
>>>>>>> texto-alternativo
</h1>
Después de resolver manualmente podría quedar:
Sin marcadores, y con un texto que combina ambas intenciones.
Preparar nuevamente el archivo¶
Una vez resuelto el contenido:
Este comando marca el conflicto como resuelto para ese archivo. Git considera que ya tiene una nueva versión coherente.[web:136]
Finalizar el merge¶
Luego, confirma el merge con un commit:
Este commit representa la resolución del conflicto y completa el merge.[web:136]
Comprobar el resultado¶
Puedes usar:
para ver el commit de merge y confirmar que la historia ahora incluye tanto el trabajo de pagina-contacto como el de texto-alternativo.
Diagrama del flujo de resolución manual¶
flowchart TD
A[Merge produce conflicto en index.html] --> B[Abrir archivo y localizar marcadores]
B --> C[Decidir contenido final]
C --> D[Eliminar marcadores y guardar]
D --> E[git add index.html]
E --> F[git commit para finalizar merge]
F --> G[Historial actualizado sin conflictos]
Buenas prácticas
Tómate el tiempo necesario para leer ambos bloques en conflicto. No se trata solo de elegir uno u otro: muchas veces la mejor solución combina partes de ambos.[web:141]
Error común
Olvidar eliminar los marcadores de conflicto antes de hacer
git add. Eso puede dejar símbolos extraños en el código y provocar errores posteriores.[web:127]
Breve conclusión: resolver conflictos manualmente implica editar el archivo, decidir el contenido final, eliminar los marcadores y registrar la resolución con git add y un nuevo commit de merge.
7.6 Resolviendo conflictos con Visual Studio Code¶
Visual Studio Code ofrece una experiencia visual muy cómoda para resolver conflictos. La documentación oficial describe que, cuando se detectan conflictos, VS Code muestra un editor especial con acciones como Accept Current Change, Accept Incoming Change, Accept Both Changes y Compare Changes.[web:129][web:140]
Current Change e Incoming Change¶
Cuando abres un archivo con conflicto en VS Code:
- Current Change representa los cambios de tu rama actual (lo que estaba bajo
HEAD).[web:140] - Incoming Change representa los cambios de la rama que estás intentando fusionar (lo que estaba bajo
>>>>>>> nombre-rama).[web:140]
VS Code coloca etiquetas y botones sobre el archivo para que puedas aceptar una u otra versión con un clic.
Accept Current / Accept Incoming / Accept Both¶
Encima de cada bloque en conflicto verás opciones como:[web:129][web:140]
- Accept Current Change: conserva solo tu versión.
- Accept Incoming Change: conserva solo la versión de la otra rama.
- Accept Both Changes: mantiene ambas versiones, normalmente una debajo de la otra, para que luego las edites si es necesario.
Estas acciones reemplazan manualmente el contenido marcado por Git y eliminan los marcadores internos.
Compare Changes¶
VS Code también ofrece una opción de Compare Changes, que abre una vista diff entre tu cambio y el cambio entrante.[web:140] Esto te ayuda a entender mejor qué diferencia hay entre ambos bloques antes de decidir.
Ejemplo aplicado al proyecto del libro¶
Supón que tienes el conflicto en index.html y lo abres en VS Code:
- Ves el bloque de conflicto con etiquetas de Current Change y Incoming Change.
- Haces clic en Accept Both Changes para mantener ambas versiones.
- Editas manualmente el resultado combinado para crear un título definitivo.
- Guardas el archivo.
- Desde el panel Source Control, preparas el archivo y haces el commit de resolución.
[Ilustración: interfaz de VS Code mostrando un archivo con conflicto, etiquetas “Current Change” y “Incoming Change”, botones de “Accept Current”, “Accept Incoming”, “Accept Both” y enlace “Compare Changes”, con el bloque en conflicto claramente resaltado]
Flujo visual de resolución en VS Code¶
flowchart TD
A[Conflicto en index.html] --> B[Abrir archivo en VS Code]
B --> C[Ver Current vs Incoming Change]
C --> D[Elegir Accept Current / Incoming / Both]
D --> E[Editar resultado si es necesario]
E --> F[Guardar archivo y preparar cambios]
F --> G[Commit para finalizar merge]
Consejo
Usa VS Code para los conflictos más complejos: la vista visual y las acciones guiadas hacen mucho más fácil entender qué está ocurriendo.[web:129][web:140]
Error común
Pulsar “Accept Current” o “Accept Incoming” sin revisar el contenido y descubrir luego que se perdió información importante de la otra rama.
Breve conclusión: VS Code convierte la resolución de conflictos en un proceso visual guiado. Las opciones de aceptar cambios actuales, entrantes o ambos te permiten tomar decisiones rápidas sin pelear con los marcadores manualmente.
7.7 Buenas prácticas para evitar conflictos¶
Aunque los conflictos nunca desaparecen por completo, sí puedes reducir su frecuencia mediante buenas prácticas. Muchos recursos y guías coinciden en varios principios clave.[web:128][web:131]
Commits pequeños y claros¶
Hacer commits pequeños y bien enfocados ayuda a:
- reducir el área de impacto de cada cambio;
- entender mejor qué causó un conflicto;
- facilitar la resolución cuando aparece.
Sincronizar frecuentemente¶
Si trabajas con un remoto (como GitHub):
- haz
pullcon regularidad; - publica tus cambios (
push) de forma ordenada.
Esto minimiza las diferencias acumuladas entre tu copia y la de otros (o la tuya misma desde otro equipo).
Trabajar en ramas independientes¶
Como viste en el capítulo 6, crear ramas para funcionalidades específicas reduce el riesgo de mezclar cambios sin relación. Aunque aún pueden aparecer conflictos, estarán más aislados y serán más fáciles de entender.[web:102]
Mantener ramas actualizadas¶
Si una rama de larga duración se queda muy atrás respecto a main, es más probable que el merge final sea conflictivo. Mantenerla actualizada periódicamente (haciendo merges desde main hacia la rama de trabajo) puede reducir esos choques.
Comunicar cambios importantes¶
En un contexto educativo o profesional, comunicar que vas a cambiar una parte sensible del código (como el título principal, la estructura de navegación o un componente compartido) ayuda a coordinar esfuerzos y evitar sorpresas.
| Buena práctica | Efecto sobre los conflictos |
|---|---|
| Commits pequeños | Facilita entender y resolver conflictos |
| Sincronizar con frecuencia | Reduce diferencias acumuladas |
| Usar ramas para funcionalidades | Aísla cambios y mejora el orden |
| Mantener ramas actualizadas | Disminuye conflictos grandes al final |
| Comunicar cambios clave | Evita modificaciones incompatibles simultáneas |
Buenas prácticas
Acepta que los conflictos son parte del trabajo, pero usa estas estrategias para que aparezcan menos y sean más fáciles de manejar cuando surjan.[web:128]
Breve conclusión: los conflictos no pueden eliminarse por completo, pero puedes reducir su frecuencia y complejidad mediante commits pequeños, sincronización frecuente, ramas bien usadas y comunicación clara.
7.8 Un conflicto no es un problema¶
Después de todo lo visto, es momento de cambiar definitivamente la forma en que ves los conflictos de Merge.
Resolver conflictos es una habilidad profesional¶
Cualquier desarrollador que trabaje con Git en proyectos reales se encontrará con conflictos. Eso incluye:[web:128][web:131]
- docentes que mantienen material de clase en repositorios Git;
- estudiantes que colaboran en trabajos de curso;
- profesionales que contribuyen a proyectos de código abierto o privados.
La diferencia entre alguien que se paraliza y alguien que sigue adelante está en la práctica para leer mensajes, entender marcadores y decidir el contenido final.
No es una señal de fracaso¶
Un conflicto no significa que “hiciste algo mal”. Significa que:
- hubo trabajo paralelo sobre la misma parte del código;
- Git eligió proteger ambos cambios;
- ahora tú debes actuar como árbitro.
De hecho, en proyectos activos, los conflictos son una señal de que el proyecto está vivo y se están haciendo cambios.
Cambiar tu mentalidad¶
A partir de ahora, cuando veas:
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
puedes leerlo como:
“Hay cambios importantes que necesitan tu criterio profesional. Tómate un momento, revisa y decide el mejor resultado.”
[Ilustración: escena conceptual moderna donde se muestra un desarrollador frente a pantalla con mensaje de conflicto, acompañado de elementos visuales que transmiten calma y enfoque profesional, lejos de la idea de pánico o error]
¿Sabías que...?
Grandes proyectos de software gestionan conflictos de Merge a diario. La diferencia está en tener procesos, herramientas y habilidades para resolverlos de forma sistemática.[web:130][web:128]
Breve conclusión: un conflicto de Merge no es un fallo, es una petición de ayuda por parte de Git. Resolverlo con calma y criterio forma parte del trabajo profesional.
Práctica guiada¶
En esta práctica vas a crear y resolver dos conflictos sobre el proyecto del libro: uno manualmente desde la terminal y el editor, y otro aprovechando las herramientas visuales de VS Code.
Conflicto 1: resolución manual¶
- Partiendo de
mainestable, crea dos ramas que modifiquen la misma sección deindex.html(como hicimos en la sección 7.2). - Realiza los commits en cada rama.
- Haz merge de una rama en
main. - Intenta merge de la segunda rama para provocar el conflicto.
- Observa el mensaje de Git y usa
git statuspara identificar el archivo en conflicto.[web:128][web:136] - Abre el archivo en tu editor y analiza los marcadores
<<<<<<<,=======,>>>>>>>.[web:141] - Decide el contenido final y edita el archivo para reflejarlo.
- Elimina los marcadores y guarda.
- Ejecuta
git add index.htmlpara marcar la resolución. - Confirma el merge con
git commit. - Usa
git logpara ver el commit de merge y confirmar el historial.
Conflicto 2: resolución con VS Code¶
- Repite un escenario similar creando dos ramas que modifiquen otra sección de
index.htmlocontacto.html. - Provoca el conflicto de Merge desde la terminal.
- Abre el proyecto en VS Code.
- Observa cómo el panel Source Control destaca archivos en conflicto.
- Abre el archivo en conflicto y revisa las etiquetas Current Change y Incoming Change.[web:129][web:140]
- Usa las acciones Accept Current Change, Accept Incoming Change o Accept Both Changes según el caso.
- Edita el resultado si es necesario y guarda.
- Desde el panel Source Control, prepara el archivo y realiza el commit de resolución.
- Verifica que el conflicto desapareció y que el merge quedó registrado.
Diagrama del flujo de resolución de conflictos¶
flowchart TD
A[Crear ramas con cambios divergentes] --> B[Intentar merge]
B --> C[Git detecta conflicto y marca archivos]
C --> D[Leer mensaje y analizar marcadores]
D --> E[Resolver manualmente o con VS Code]
E --> F[git add para marcar resolución]
F --> G[git commit para finalizar merge]
G --> H[Historial sin conflictos]
[Ilustración: vista combinada donde se muestra primero un archivo con marcadores de conflicto y luego la interfaz de VS Code con acciones de resolución, conectando visualmente ambos enfoques]
Lista de comprobación¶
Al terminar esta práctica deberías haber logrado:
- Crear dos ramas sobre el proyecto del libro con cambios en la misma sección de un archivo.
- Generar al menos un conflicto de Merge real.[web:128]
- Interpretar correctamente el mensaje de conflicto y el estado del repositorio.[web:136]
- Resolver un conflicto manualmente editando los archivos y eliminando los marcadores.[web:141]
- Resolver un segundo conflicto utilizando las herramientas visuales de VS Code.[web:129][web:140]
- Finalizar correctamente los merges con commits claros.
- Verificar el historial para confirmar que los conflictos quedaron atrás.
Buenas prácticas
Después de cada resolución de conflicto, revisa con calma el código afectado y el historial. No se trata solo de “hacer que desaparezca el mensaje”, sino de asegurarte de que el resultado final es coherente.
Breve conclusión: la práctica guiada te muestra que puedes provocar, entender y resolver conflictos con seguridad, tanto de forma manual como apoyándote en VS Code. Esa experiencia es la base para manejar conflictos en proyectos más grandes.
Cierre del capítulo¶
En este capítulo has visto que los conflictos de Merge no son un fallo, sino una consecuencia natural del trabajo paralelo sobre un mismo proyecto. Aprendeiste por qué aparecen, cómo se manifiestan en los mensajes de Git y cómo se marcan dentro de los archivos mediante los bloques <<<<<<<, ======= y >>>>>>>.[web:128][web:141]
También practicaste la resolución manual (editando archivos, eliminando marcadores y confirmando merges) y la resolución visual usando Visual Studio Code con opciones como Current Change, Incoming Change, Accept Both y Compare Changes.[web:129][web:140] Además, incorporaste buenas prácticas para reducir la frecuencia de conflictos y cambiaste tu forma de verlos: ya no como problema, sino como una oportunidad para ejercer criterio profesional.