12 Resolución de conflictos
Cuando vamos a aceptar solicitudes de fusión puede suceder que el ixplorer nos avise que no se puede realizar la fusión debido a que hay conflictos.
12.1 ¿Qué es un conflicto?
Lo primero a aclarar es que un conflicto no es un error. Cuando surge se refiere a que git no puede fusionar el código debido a que en la historia del proyecto no se sabe cuál es el último cambio que ocurrió y por ende la última versión del código.
Al tener en una misma línea de código dos diferencias sin información sobre cuál fue la última en modificarse, git deja a criterio del usuario la elección del cambio.
Por esta razón, cuando hay una petición de fusión en el ixplorer y nos aparece un mensaje como el siguiente:
12.2 ¿Cómo proceder con la resolución del conflicto?
Para esto hay que actualizar nuestro repositorio local con el upstream. En el ejemplo estamos viendo que la solicitud de Pedro no puede ser fusionada puesto que hay un conflicto.
Lo que Pedro debe de realizar es una actualización de su repositorio local con el repositorio “upstream”. Esto se puede realizar con los siguientes pasos en la línea de comando:
12.2.1 Agregar el repositorio usptream
git remote add upstream https://github.com/nombre_proyecto/nombre_repositorio.git
12.2.1.0.1 Traer últimos cambios del upstream
Este paso nos trae todos los cambios que hay en ese repositorio sin mezclarlos con alguna de nuestras ramas locales:
git fetch upstream
NUestro personaje Pedro vería lo siguiente:
12.2.2 Re-escribir historia de cambios
Ahora re-escribimos nuestra rama master de tal manera que nuestros commits que aún no se encuentran en el repositorio remoto sean colocados sobre los de cualquier otra rama. La recomendación en este paso es asegurarnos estar en la rama master.
git checkout master
git rebase upstream/master
En el caso de Pedro, la consola mostraría un mensaje:
A este punto Pedro tendría su rama master con los últimos cambios del upstream, sin embargo recordemos que Pedro se encontraba trabajando en la rama T10 y justo fue ésta rama la que estaba siendo sometida a una solicitud de fusión, lo que causó el conflicto.
A este punto la rama T10 de Pedro sigue sin actualizaciones. La rama actualizada de Pedro es la master. El siguiente paso que debe de hacer Pedro es llevar los cambios de su rama master a su rama T10 para actualizarla también.
Estos cambios se darán en su repositorio local. Para realizar la acción de actualización de su rama T10 con lo que tiene en su rama master puede hacer lo siguiente:
Primero ir a su rama T10
git checkout T10
Ahora debe generar una fusión de su rama master a su rama T10. Ninguna rama desaparece por la fusión, simplemente se implementan los cambios de una rama en la otra.
git merge master
Y justo en este paso, a Pedro le aparece un mensaje que ya se nos hace conocido:
Hay un conflicto al hacer el merge. Es en este punto donde manualmente debemos de hacer la corrección del conflicto. Si miramos con atención el mensaje, git nos indica cuál es el archivo donde existe el conflicto. En el caso de Pedro es el archivo clean_data.R
Al abrir ese archivo Pedro encontrará la siguiente estructura que coloca git para guiarnos indicando donde se encuentra el conflicto que no puede resolver automáticamente:
<<<<<<< HEAD
=======
>>>>>>> master
Entre HEAD y los símbolos de igualdad tenemos nuestro código. Entre los símbolos de igualdad y master tenemos el código que queremos fusionar. Es decir, estos son los segmentos de código que debemos de decidir entre fusionar o eliminar.
En su archivo se mira de la siguiente manera:
Recordemos que en el caso de Pedro lo que viene de master es la actualización que hizo del repositorio upstream. ¿Cómo decidir qué dejar? Pedro puede conversar con sus compañeros para resolver si deja su código o bien los cambios que estaban en el upstream. Esta decisión depende de cada equipo.
Una vez tomada la decisión y corregido el código (borrar la estructura guía de git) se puede proceder a guardar los cambios y hacer un commit de estos.
12.2.2.0.1 Actualizar nuestra bifurcación remota
Finalmente subimos nuestra rama actualizada a nuestro repositorio remoto y con esto el conflicto en la solicitud de fusión se habrá resuelto
git push
Los pasos de Pedro en la línea de comando se verían así:
Ahora al equipo de Pedro le resta solo un paso para integrar los cambios producto de su trabajo: fusionar la petición en el ixplorer:
12.3 Conflictos en un rebase
Si uno se encuentra con conflictos en un rebase, una forma de solucionarlos forzando a git a aceptar los cambios en el rebase. Este paso debe de considerarse como última opción.
Para realizar este proceso, primero, tenemos que haber realizado tres pasos para haber obtenido el conflicto, a saber:
git remote add upstream /url/a/repositorio/madre
git fetch upstream
git rebase upstream/master
Cuando se nos informa que no se puede proceder con el rebase y no hemos podido solventarlo, podemos forzar el proceso con cuidado de tener presente que los últimos cambios están correctos. Para esto seguimos los siguientes comandos en la terminal:
git checkout master
git reset --hard upstream/master
Una vez realizado el reset --hard
podemos llevar los cambios actualizados a nuestra bifurcación a través de un push, pero para que nuestra bifurcación los acepte, debe de ser forzado:
git push origin master --force