- ¿Qué es un Conflicto de Merge en Git?
- Tipos de Merge
- Tipos de Conflicto de Merge en Git
- Comandos para Resolver Conflicto de Merge en Git
- Herramientas de Merge Visuales
- Cómo Resolver un Conflicto de Merge en Git
- Conclusión
¿Qué es un Conflicto de Merge en Git?
El sistema de control de versiones Git se basa en trabajar en equipo y contribuir a proyectos. Los desarrolladores generalmente trabajan en ramas aisladas y, cuando terminan, fusionan los cambios con la rama principal. Este tipo de trabajo en equipo es altamente productivo y efectivo para encontrar errores. A veces varios desarrolladores están trabajando en la misma línea de código y, cuando intentan fusionar los cambios, surgen conflictos.
Ejemplo Sencillo de Conflicto en Git
El diagrama de arriba da un ejemplo perfecto de cómo ocurre un conflicto de fusion en Git típico. La rama principal contiene un archivo que contiene el texto “HELLO, WORLD!”. El usuario abid realiza una bifurcación de la rama principal y cambia el texto a “HELLO, CAT!”. Mientras abid realiza cambios, la rama principal original también se modifica a “HELLO, DOG!”. La fusión de estas ramas provocará un problema de fusión de conflictos y detendrá el proceso.
La tarea principal del comando `git merge` es combinar dos ramas y resolver automáticamente los conflictos. Sin embargo, a veces surgen conflictos donde dos personas han cambiado la misma línea de código o eliminado archivos críticos que otro desarrollador estaba trabajando. Git marcará estos cambios y detendrá el proceso de fusión. En este caso, el conflicto no se ha resuelto automáticamente; en su lugar, el desarrollador tiene que hacer cambios manualmente o utilizar herramientas para resolver el conflicto.
Tipos de fusiones
Git merge y rebase son dos maneras de integrar los commits de la rama objetivo a la rama fuente. Además, Git merge realiza una fusión de fast-forward o una fusión no-fast-forward. Si la cabeza de la rama objetivo existe en la rama fuente, entonces por defecto, el tipo de fusión será una fusión de fast-forward y si falta, entonces será una fusión no-fast-forward. Git rebase es otro tipo de fusión que reescala la historia de los commits de la rama objetivo.
Fusión de fast-forward
Por defecto, Git merge utiliza el modo fast-forward para integrar commits faltantes en la rama de destino. Por ejemplo, se utiliza para actualizar una rama local desde un servidor remoto usando el comando pull. Fast-forward no plantea problemas de conflictos de fusión, ya que Git no lo aplicará si falta la cabeza de la rama de destino en la rama de origen.
Fusión sin fast-forward
Una fusión sin fast-forward también se llama fusión de tres vías o verdadera fusión. Crea un nuevo commit en una rama de destino integrando los cambios en ambas la rama de origen y la rama de destino. Los cambios se mezclan después del último commit común en ambas ramas. En nuestro caso, es después de C. Este tipo de fusión generará un conflicto de Git merge si la rama de origen está en disputa con la rama de destino. En el diagrama anterior, el commit de fusión (X) se crea integrando la rama de origen y la rama de destino, donde K y E son los padres del commit de fusión.
Rebase
Git rebase es un poco diferente de los otros tipos. Cambia la secuencia de historial de commits de la rama de destino. El rebase integra la rama de origen de manera que la rama de destino contenga todos los cambios de la rama de origen, seguidos de todos los commits de la rama de destino después del último commit común. En nuestro caso, el último commit común es C, mientras que D y E son de la rama de origen. El commit K* es el mismo que K con un identificador de commit diferente. En lugar de enlazar con C, se enlazará con E. Similar a una fusión sin fast-forward, si hay problemas de compatibilidad en la rama de origen y la rama de destino, Git planteará un problema para resolver el conflicto antes de finalizar el rebase.
Tipos de conflictos de fusión de Git
Hay dos tipos de conflictos de fusionar en Git: al inicio y durante el proceso de fusión – Atlassian. En esta sección, aprenderíamos sobre ambos tipos y las maneras de resolver cada escenario.
Al Inicio de la Fusion
Git fusionará sin éxito al inicio si hay cambios en el directorio de trabajo o en el área de preparación. Falla al inicio para evitar que los cambios sean sobrescritos por los commit de fusión entrantes. Esto sucede debido a conflictos con los cambios locales, no con otras ramas o desarrolladores. Para estabilizar el estado local, se pueden utilizar comandos como git stash
, git commit
, git checkout
, o git reset
.
Durante la Fusion
Un fallo durante la fusión significa que hay un conflicto entre la rama de origen y la rama de destino donde varios desarrolladores han modificado el mismo archivo. Si la fusión automática falla, Git le pedirá que resuelva los problemas manualmente. También se pueden utilizar herramientas de terceros para asistirlo en la visualización e integración de los cambios.
Comandos para Resolver Conflictos de Fusionar en Git
En esta sección, aprenderíamos sobre varios comandos nativos para visualizar y resolver los conflictos de fusionar en Git.
Comandos Comunes
Git status es el comando más frecuentemente utilizado para mostrar el estado de los archivos modificados, el área de preparación y los commit. Durante el proceso de fusión, se utiliza para identificar los archivos en conflicto.
git status
El registro de Git con los argumentos –merge produce la lista de commit que están en conflicto con la rama de origen.
git log --merge
Por defecto, la opción git diff
mostrará la diferencia entre los cambios no commitados y los commit anteriores. Git diff se utiliza para comparar las ramas, commit y archivos. Es útil para evitar futuros conflictos de fusiones.
git diff
Comandos para Fallos en la Fusión al Inicio
El comando checkout se utiliza para deshacer cambios o cambiar a una nueva o antigua rama.
git checkout
El reset de Git se utiliza para revertir los cambios en el directorio de trabajo y en el área de preparación.
git reset --mixed
Comandos para Conflictos Durante la Fusión
El argumento –abort detendrá el proceso de fusión y revertirá los cambios a su estado original antes de que comenzara la fusión.
git merge --abort
El reset de Git generalmente se utiliza durante el proceso de fusión para revertir los archivos en conflicto a su estado original.
git reset
Resolver conflictos de archivos eliminados-modificados
Si se elimina el archivo en la rama actual y alguien else lo modifica en otra rama, se producirá un conflicto de Git. En este caso, puede agregar un archivo y commit,
git add <filename>
o puede eliminar el archivo y commit.
git rm <filename>
Herramientas de fusión visual de Git
Herramientas de fusión son herramientas visuales amigables para el usuario que identifican y resuelven todo tipo de conflictos de fusión. Algunas de las herramientas admiten capacidades adicionales, como comparar cambios, operaciones de Git y gestión de proyectos y repositorios. Hay dos tipos de herramientas de fusión de Git: solo de terminal y basadas en GUI. Las herramientas basadas en terminal se abren en PowerShell o Bash, y las herramientas basadas en GUI se abren en un entorno de ventana.
Para verificar la lista de herramientas instaladas y válidas, use:
git mergetool --tool-help
La lista consiste en todas las herramientas válidas que se pueden instalar e integrar con comandos de git.
Por ejemplo, tenemos vim y nvim instalados de forma predeterminada, y si desea ver la diferencia entre un archivo sin enviar y un commit anterior, escriba:
git difftool --tool=vimdiff3
La herramienta vimdiff3 resalta los cambios y le permite comparar commits dentro de la terminal.
Diferencia Entre Dos Versiones del Mismo Archivo en Vimdiff3
Meld
Meld es una herramienta gratuita y de código abierto que lleva la resolución de conflictos de fusión a otro nivel. Para integrarla con Git, primero debe descargar e instalar la configuración desde el sitio oficial. A continuación, añadalo a la configuración global para que, de forma predeterminada, Git lance Meld para resolver conflictos.
Los comandos de configuración a continuación solo son aplicables a los usuarios de Windows. El único cambio que debe realizar es cambiar la ruta del archivo instalado de Meld para Mac o Linux.
git config --global merge.tool meld git config --global mergetool.meld.path "C:/Program Files (x86)/Meld/Meld.exe" git config --global diff.tool meld git config --global difftool.meld.path "C:/Program Files (x86)/Meld/Meld.exe"
Después de configurar los valores predeterminados, puede escribir git difftool
dentro del directorio local de Git para lanzar la versión de Windows de Meld, o puede usar git mergetool
para resolver los conflictos de fusion como se muestra a continuación.
Resolviendo un Conflicto de Fusion con Meld
VSCode
VSCode proporciona la mejor y manera más popular para resolver el conflicto de fusion. Cuando Git no puede fusionar automáticamente los archivos, VSCode resalta el código conflictivo y le ofrece cuatro opciones: aceptar los cambios actuales, aceptar los cambios entrantes, aceptar ambos cambios y comparar cambios. Puede usar estas opciones para limpiar su archivo y resolver todos los problemas pendientes.
Resolviendo Conflicto de Fusion con VSCode
Si busca una solución completa para sus operaciones de Git, pruebe GitKraken. Viene con un cliente gratuito, extensiones de VSCode, y proporciona una herramienta integrada para resolver conflictos de fusion.
Cómo Resolver un Conflicto de Fusion de Git
En esta sección, vamos a aprender cómo crear un conflicto de fusion de Git y luego resolverlo. El tutorial se divide en dos partes. En la primera parte, aprenderemos a resolver conflictos de Git localmente; la segunda parte se refiere a la resolución de conflictos con un servidor remoto (GitHub).
Conflicto de Fusion Local
Crear conflictos de fusion nos ayudará a comprender cómo surgen estos problemas en primer lugar. Luego, podremos utilizar maneras creativas para resolver estos problemas o incluso evitar que ocurran en el futuro.
Ahora crearemos un repositorio de Git con un solo archivo y crearemos nuestro primer commit para empezar.
- Cree una carpeta llamada datacamp.
- Cambie de directorio a datacamp.
- Inicialice Git.
- Cree un archivo README.md con el título dado.
- Escenario y commit los cambios en un archivo.
mkdir datacamp cd datacamp git init echo "# How to Resolve Git Merge Conflict" > README.md git add README.md git commit -m "first commit" >>> [main (root-commit) 8199ea2] first commit >>> 1 file changed, 1 insertion(+) >>> create mode 100644 README.md
Después, crearemos una nueva rama llamada readme y cambiará el título de “..Git Merge..” a “..Git..”. Agregue el archivo y cree el commit usando el argumento -am.
git checkout -b readme echo "# How to Resolve Git Conflict" > README.md git commit -am "new branch conflict added" >>> [readme 155f694] new branch conflict added >>> 1 file changed, 1 insertion(+), 1 deletion(-)
Vuelva a la rama principal y agregue una nueva línea al archivo README.md usando >>. Al guardar los cambios y crear commit, ha creado exitosamente un conflicto entre dos versiones del mismo archivo.
git checkout main echo "New change in base branch" >> README.md git commit -am " a line added to base branch Readme file" >>> [main f1f1874] a line added to base branch Readme file >>> 1 file changed, 1 insertion(+)
Como podemos ver, mientras se fusionaba la rama readme, Git le mostró un mensaje diciendo que la fusión automática ha fallado y que debemos hacer cambios manualmente y luego commitar el resultado.
git merge readme >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.
Resolveremos manualmente el problema abriendo y editando el archivo en Notepad. La imagen de abajo muestra una flecha con HEAD, un divisor, y una flecha en dirección diferente con un readme. La parte HEAD muestra los cambios existentes en el principal, y la parte readme es la rama que queremos fusionar, que consiste en un encabezado diferente.
Resolución de un Conflicto de Fusiones Manualmente
Para resolver el problema, eliminaremos la parte de la rama readme, las flechas y el divisor. La versión final del archivo debe verse limpia, como se muestra a continuación.
Conflicto Resuelto
Después de agregar el archivo y crear un commit, se resolverá el conflicto de fusiones. Es la forma más común y sencilla de resolver problemas. También se puede utilizar un entorno de desarrollo integrado (IDE) para resolver problemas más rápido.
git commit -am "conflict resolved in file README.md" >>> [main 9994a29] conflict resolved in file README.md
Conflicto de Fusiones Remoto
Para crear y resolver conflictos de fusiones remotos, necesitamos crear un nuevo repositorio en GitHub.
Creando un Nuevo Repositorio en GitHub
A continuación, agregue el nombre remoto (origin) con la dirección al repositorio y propulse todos los cambios del repositorio local al branch principal remoto usando upstream.
git remote add origin https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git git push --set-upstream origin main >>> Enumerating objects: 12, done. >>> Counting objects: 100% (12/12), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (12/12), 998 bytes | 499.00 KiB/s, done. >>> Total 12 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), done. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> * [new branch] main -> main >>> branch 'main' set up to track 'origin/main'.
Para crear un conflicto, necesitamos realizar cambios en el archivo README.md remoto y local. Puede usar el editor de archivos de GitHub para cambiar “..Git merge..” a “..Sit-Merge..” y luego hacer el commit de los cambios.
Realizar Cambios en el Editor de GitHub
Después, en el repositorio local, cambie el archivo README.md para agregar solo un título simple y haga el commit de los cambios.
echo "# How to Resolve Merge Conflicts in Git Tutorial" > README.md git commit -am "local branch changes in README.md" >>> [main c677a13] local branch changes in README.md >>> 1 file changed, 1 insertion(+), 4 deletions(-)
Finalmente, propulse los cambios al servidor remoto. Note que Git ha lanzado un error con sugerencias sobre cómo eliminar el problema.
git push >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> ! [rejected] main -> main (fetch first) >>> error: failed to push some refs to 'https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git' >>> hint: Updates were rejected because the remote contains work that you do >>> hint: not have locally. This is usually caused by another repository pushing >>> hint: to the same ref. You may want to first integrate the remote changes >>> hint: (e.g., 'git pull ...') before pushing again. >>> hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Seguiremos la sugerencia más simple, que es obtener el archivo del servidor remoto antes de propulsar.
La extracción del archivo falló debido a un conflicto de fusión en el archivo README.md. Podríamos arreglarlo manualmente usando Bloc de Notas, pero esta vez usaremos una herramienta visual para ayudarnos en este proceso.
git pull >>> remote: Enumerating objects: 5, done. >>> remote: Counting objects: 100% (5/5), done. >>> remote: Compressing objects: 100% (2/2), done. >>> remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 >>> Unpacking objects: 100% (3/3), 681 bytes | 75.00 KiB/s, done. >>> From https://github.com/kingabzpro/DataCamp-Git-Merge-Guide >>> aaf149d..49b7d14 main -> origin/main >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.
La herramienta de fusión Meld identificará los archivos en conflicto y los mostrará en la aplicación de interfaz gráfica de Meld.
git mergetool >>> Merging: >>> README.md >>> Normal merge conflict for 'README.md': >>> {local}: modified file >>> {remote}: modified file
Hay tres columnas: README_LOCAL_473.md, README.md, y README_LOCAL_473.md. Si cree que los cambios remotos son válidos, entonces haga clic en la flecha negra en la columna remota; y si quiere que los cambios locales persistan, entonces haga clic en la flecha negra en la columna local. Es así de simple.
Conflicto Resuelto Utilizando el Herramienta de Fusión Meld
Después de realizar cambios, guarde el archivo y commité. Como puede ver, al publicar un archivo en un servidor remoto no se produce un error de fusión de merges.
git commit -am "remote main branch conflict resolved" git push >>> Enumerating objects: 16, done. >>> Counting objects: 100% (16/16), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (10/10), 1.08 KiB | 550.00 KiB/s, done. >>> Total 10 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), completed with 1 local object. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> 49b7d14..8f5c3aa main -> main
Hemos resuelto correctamente ambos conflictos de fusión local y remoto. Estos conflictos se manejan diariamente por científicos de datos y ingenieros en aprendizaje automático. Para mejorar sus habilidades en operaciones de Git, tome un curso de Introducción a Git.
Conclusión
Resolver conflictos de fusión en Git es una tarea compleja y altamente arriesgada ya que puede romper el software fusionando código defectuoso. Las herramientas de fusión proporcionan un entorno amigable para el usuario con una manera más segura para detectar y resolver conflictos de fusión. En este tutorial, hemos aprendido por qué ocurren conflictos en Git y cómo resolverlos. También hemos cubierto varios tipos de fusión y conflictos, órdenes de Git útiles y herramientas visuales. En la sección final, creamos un conflicto de fusión y lo resolvimos en un repositorio local y remoto.
Si es nuevo en Git y quiere aprender cómo funciona, lea: Introducción a Git y Tutorial de GitHub.</
Source:
https://www.datacamp.com/tutorial/how-to-resolve-merge-conflicts-in-git-tutorial