Revisar diferencias antes de merge
Antes de fusionar ramas, es fundamental revisar las diferencias entre ellas para entender exactamente qué cambios se van a integrar. Esta práctica te permite identificar posibles conflictos, verificar que los cambios son los esperados y tomar decisiones informadas sobre la fusión.
Comparar ramas con git diff
El comando git diff
te permite comparar el contenido entre diferentes ramas de forma detallada. La sintaxis básica para comparar ramas es:
git diff rama-origen..rama-destino
Por ejemplo, si quieres ver qué cambios tiene la rama feature/login
respecto a main
:
git diff main..feature/login
Este comando muestra todas las diferencias línea por línea entre ambas ramas, indicando qué se ha añadido, modificado o eliminado.
Opciones útiles para revisar diferencias
Mostrar solo los archivos modificados:
git diff --name-only main..feature/login
Ver estadísticas de cambios:
git diff --stat main..feature/login
Este comando proporciona un resumen estadístico mostrando cuántas líneas se han añadido y eliminado en cada archivo.
Comparar archivos específicos:
git diff main..feature/login -- src/auth.js
Revisar commits únicos entre ramas
Para ver qué commits específicos existen en una rama pero no en otra, utiliza:
git log main..feature/login --oneline
Esto muestra todos los commits que están en feature/login
pero no en main
, presentados de forma compacta con una línea por commit.
Si quieres ver los commits en ambas direcciones:
git log --left-right --graph --oneline main...feature/login
Los commits de main
aparecen marcados con <
y los de feature/login
con >
.
Verificar el estado actual
Antes de realizar cualquier comparación, asegúrate de que tu repositorio local esté actualizado:
git fetch origin
git status
Es importante verificar que no tienes cambios pendientes en tu área de trabajo que puedan interferir con la revisión.
Comparar con el remoto
Si trabajas con un repositorio remoto en GitLab, puedes comparar tu rama local con la versión remota:
git diff origin/main..feature/login
Esto te permite ver las diferencias entre tu rama local y la versión más reciente de main
en el servidor remoto.
Revisar cambios por autor o fecha
Para filtrar los cambios por criterios específicos, puedes combinar git log
con opciones adicionales:
git log main..feature/login --author="nombre-usuario" --since="2024-01-01"
Esta revisión previa te proporciona la información necesaria para decidir si proceder con la fusión, si necesitas hacer ajustes adicionales, o si es mejor coordinar con otros miembros del equipo antes de integrar los cambios.
Fusionar cambios con merge
Una vez que has revisado las diferencias entre ramas y confirmado que los cambios son correctos, el siguiente paso es fusionar las ramas utilizando el comando git merge
. Este proceso integra los commits de una rama en otra, creando un historial unificado de tu proyecto.
Tipos de merge en Git
Git maneja la fusión de diferentes maneras según el estado del historial de las ramas involucradas:
Fast-forward merge: Ocurre cuando la rama destino no ha tenido commits adicionales desde que se creó la rama origen. Git simplemente mueve el puntero de la rama destino hacia adelante.
Three-way merge: Se produce cuando ambas ramas han divergido con commits independientes. Git crea un commit de merge que combina los cambios de ambas ramas.
Realizar un merge básico
Para fusionar una rama en la rama actual, utiliza:
git merge nombre-rama
Por ejemplo, si estás en main
y quieres fusionar feature/login
:
git checkout main
git merge feature/login
Git intentará fusionar automáticamente los cambios. Si no hay conflictos, el merge se completará exitosamente.
Merge con mensaje personalizado
Puedes especificar un mensaje personalizado para el commit de merge:
git merge feature/login -m "Integrar sistema de autenticación"
Esto es especialmente útil para documentar el propósito de la fusión en el historial del proyecto.
Estrategias de merge
Git ofrece diferentes estrategias de fusión que puedes especificar según tus necesidades:
Forzar un commit de merge:
git merge --no-ff feature/login
La opción --no-ff
(no fast-forward) crea siempre un commit de merge, incluso cuando sería posible un fast-forward. Esto mantiene la estructura de ramas visible en el historial.
Merge con squash:
git merge --squash feature/login
Esta opción toma todos los cambios de la rama origen pero los combina en un solo commit en lugar de preservar el historial individual de commits.
Verificar el resultado del merge
Después de realizar un merge exitoso, puedes verificar el resultado:
git log --oneline --graph -10
Este comando muestra los últimos 10 commits con una representación gráfica del historial, permitiéndote ver cómo se han integrado las ramas.
Para ver específicamente el commit de merge:
git show HEAD
Merge desde repositorio remoto
Si trabajas con GitLab y necesitas fusionar cambios desde el remoto:
git fetch origin
git merge origin/feature/login
Primero actualizas las referencias remotas con fetch
y luego realizas el merge desde la rama remota.
Abortar un merge en progreso
Si durante el proceso de merge decides que no quieres continuar, puedes cancelar la operación:
git merge --abort
Este comando restaura el repositorio al estado anterior al inicio del merge, deshaciendo cualquier cambio parcial.
Buenas prácticas para merge
Actualiza la rama destino antes del merge:
git checkout main
git pull origin main
git merge feature/login
Elimina ramas fusionadas para mantener el repositorio limpio:
git branch -d feature/login
La opción -d
elimina la rama solo si ha sido completamente fusionada. Si necesitas forzar la eliminación, usa -D
.
Verifica el estado después del merge:
git status
git log --oneline -5
Merge con ramas divergentes
Cuando ambas ramas han evolucionado independientemente, Git crea un commit de merge que tiene dos padres. Este escenario es común en equipos donde múltiples desarrolladores trabajan simultáneamente:
# Situación: main y feature/api han divergido
git checkout main
git merge feature/api
# Git crea automáticamente un commit de merge
El commit resultante incluye los cambios de ambas ramas y mantiene la trazabilidad completa del desarrollo paralelo.
Esta fusión exitosa integra todos los cambios de la rama origen en la rama destino, creando un punto de convergencia en el historial que refleja la colaboración entre diferentes líneas de desarrollo.
Conflictos de merge
Los conflictos de merge surgen cuando Git no puede fusionar automáticamente los cambios de dos ramas porque ambas han modificado las mismas líneas de código de formas diferentes. Esta situación es natural en el desarrollo colaborativo y Git proporciona herramientas específicas para resolverla de manera controlada.
Cuándo ocurren los conflictos
Un conflicto se produce cuando dos ramas modifican el mismo fragmento de código de manera incompatible. Por ejemplo:
- La rama
main
modifica la línea 15 deconfig.js
- La rama
feature/database
también modifica la línea 15 del mismo archivo - Git no puede determinar automáticamente cuál versión conservar
Cuando ejecutas git merge
y Git detecta conflictos, el proceso se detiene automáticamente y te solicita que resuelvas manualmente las diferencias antes de completar la fusión.
Identificar conflictos durante el merge
Cuando Git encuentra conflictos, muestra un mensaje similar a este:
git merge feature/database
Auto-merging src/config.js
CONFLICT (content): Merge conflict in src/config.js
Automatic merge failed; fix conflicts and then commit the result.
El comando git status
te muestra exactamente qué archivos tienen conflictos:
git status
Los archivos en conflicto aparecen marcados como "both modified" en la sección de cambios no preparados.
Anatomía de un conflicto
Git marca los conflictos directamente en los archivos afectados usando marcadores especiales:
function conectarBaseDatos() {
<<<<<<< HEAD
const url = 'mongodb://localhost:27017/produccion';
const opciones = { useNewUrlParser: true };
=======
const url = 'postgresql://localhost:5432/desarrollo';
const opciones = { ssl: false, pool: { max: 10 } };
>>>>>>> feature/database
return conectar(url, opciones);
}
Los marcadores indican:
<<<<<<< HEAD
: Inicio del contenido de la rama actual=======
: Separador entre las dos versiones>>>>>>> feature/database
: Final del contenido de la rama que se está fusionando
Resolver conflictos manualmente
Para resolver un conflicto, debes editar el archivo y decidir qué contenido conservar:
Opción 1 - Conservar solo la versión actual:
function conectarBaseDatos() {
const url = 'mongodb://localhost:27017/produccion';
const opciones = { useNewUrlParser: true };
return conectar(url, opciones);
}
Opción 2 - Conservar solo la versión entrante:
function conectarBaseDatos() {
const url = 'postgresql://localhost:5432/desarrollo';
const opciones = { ssl: false, pool: { max: 10 } };
return conectar(url, opciones);
}
Opción 3 - Combinar ambas versiones:
function conectarBaseDatos() {
const url = process.env.NODE_ENV === 'production'
? 'mongodb://localhost:27017/produccion'
: 'postgresql://localhost:5432/desarrollo';
const opciones = {
useNewUrlParser: true,
ssl: false,
pool: { max: 10 }
};
return conectar(url, opciones);
}
Completar la resolución de conflictos
Una vez resueltos todos los conflictos en un archivo:
1. Añadir el archivo al área de preparación:
git add src/config.js
2. Verificar que todos los conflictos están resueltos:
git status
3. Completar el merge con un commit:
git commit
Git abrirá tu editor con un mensaje predeterminado para el commit de merge. Puedes modificarlo si es necesario o mantener el mensaje automático.
Herramientas para resolver conflictos
Usar un editor de merge visual:
git mergetool
Este comando abre una herramienta gráfica configurada en tu sistema para resolver conflictos de manera más intuitiva.
Ver el conflicto en contexto:
git diff
Muestra las diferencias pendientes de resolver, útil para entender el alcance del conflicto.
Revisar el historial de cambios:
git log --merge --oneline
Muestra los commits que han contribuido al conflicto, ayudándote a comprender el contexto de cada cambio.
Prevenir conflictos futuros
Mantén las ramas actualizadas regularmente:
git checkout feature/nueva-funcionalidad
git merge main
Integrar cambios de main
frecuentemente reduce la probabilidad de conflictos grandes.
Coordina modificaciones en archivos críticos con tu equipo. Si sabes que alguien está trabajando en el mismo archivo, comunícate para evitar cambios simultáneos en las mismas secciones.
Divide el trabajo en archivos y funciones separadas cuando sea posible. Esto reduce las áreas de solapamiento entre diferentes desarrolladores.
Realiza commits pequeños y frecuentes que sean fáciles de entender y fusionar. Los cambios grandes y complejos son más propensos a generar conflictos difíciles de resolver.
Abortar la resolución de conflictos
Si decides que no quieres continuar con el merge durante la resolución de conflictos:
git merge --abort
Este comando cancela completamente el proceso de merge y restaura el repositorio al estado anterior, eliminando todos los marcadores de conflicto y cambios parciales.
La resolución de conflictos es una habilidad fundamental en Git que mejora con la práctica. Cada conflicto resuelto te ayuda a comprender mejor cómo evoluciona el código en proyectos colaborativos y te prepara para manejar situaciones más complejas en el futuro.
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en Git
Documentación oficial de Git
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Git es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Git
Explora más contenido relacionado con Git y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Comprender cómo revisar diferencias entre ramas antes de fusionarlas.
- Aprender a utilizar comandos Git para comparar ramas y commits.
- Conocer los tipos de merge y cómo realizar fusiones básicas y avanzadas.
- Identificar y resolver conflictos de merge manualmente y con herramientas.
- Aplicar buenas prácticas para evitar y manejar conflictos en proyectos colaborativos.