Al versionar un proyecto con git y trabajar junto a un equipo de devs, suelen ocurrir conflictos al tratar de unir los branches.
La semana pasada me encontré con una situación así y justo me enteré de una forma distinta de resolver conflictos. En este artículo haré un ejemplo y probaré si hay alguna diferencia al utilizar ambas estrategias.
Necesitamos la base
- Como proyecto ejemplo utilizaré un simple HTML básico con un div en él, se puede utilizar cualquier proyecto.
- Un IDE, yo utilizaré VSCode.
- Un mergetool, yo utilizaré VSCode.
- Git (obvio).
El proyecto se ve así:
El primer commit es la base del proyecto, es convención colocarle init.
Luego de tener la base creo los branches de un flujo clásico de desarrollo, no es necesario pero me gusta aproximarme a lo real:
A continuación una representación gráfica del flujo que estoy buscando crear:
El punto rojo es donde crearé el conflicto, ahora manos a la obra...
Creando el conflicto
Un conflicto ocurre cuando 2 branches tienen un cambio sobre la misma línea de código y el merge automático de git no puede reconocer que cambio debe mantenerse, por esto se debe resolver el conflicto manualmente; vamos a ellos:
Branch feature
Creo un rectángulo verde y hago commit:
Branch feature2
Creo un rectángulo azul y hago commit:
Ambos branches tienen un cambio sobre la línea 9, si los junto se genera el conflicto seguro, ahora veamos las estrategias que deseo comparar:
Estrategia 1: De development al feature branch
Esta estrategia la vi en 2 equipos de trabajo y va enfocada a mantener el feature branch siempre actualizado antes de lanzar el pull request.
- Al inicio de la semana creo mi branch a partir de development
- El miércoles a un compañero le aprueban sus cambios a development
- El jueves temprano me doy cuenta de su PR hago pull desde origin/development a mi feature branch local
- Provocará un conflicto
Replicando el cambio del miércoles
feature2 será el branch que resolvió su PR primero:
Replicando la actualización a mi branch local el jueves
Me coloco en el branch feature y hago pull desde origin/development:
Ocurrió lo que todos esperabamos, un conflicto justo en la línea que cambio el compañero el miércoles. La verdad prefiero que se quede verde el rectángulo... así que resuelvo el conflicto.
Ahora armo el PR por si ocurre algo extraño:
Resultado: Al parecer todo funciona de maravilla, me sigue pareciendo poco intuitivo; ya que, al actualizar el branch local, lanzas los cambios hacia el feature y no como el flujo de trabajo funciona, es decir:
Por otro punto de vista, he investigado ya ocasiones anteriores y es lo mejor para mantener actualizado; incluso VsCode te ayuda haciendo fetch cada cierto tiempo.
Estrategia 2: Del feature branch a una copia de development
Esta estrategia me la enseño un compañero de trabajo, va enfocada a resolver los conflictos de forma segura y siguiendo el flujo natural.
- Al inicio de la semana creo mi branch a partir de development
- El miércoles a un compañero le aprueban sus cambios a development
- El jueves temprano me doy cuenta de su PR, no hago nada al respecto
- Provocará un conflicto al crear el PR
Replicando el cambio del miércoles
Esta vez me saltaré algunos pasos, vamos directo al PR del primer cambio; agregamos un eslogan erróneo.
Replicando conflicto en el PR
Me coloco en el branch feature y hago mi PR como si no supiera que va a haber un conflicto (lo que suele ocurrir)
Procedo a resolver el conflicto en local:
- Actualizo el branch de development en local
- Creo un branch dev-conflict a partir de development y me coloco sobre él
- Ejecuto 'git merge' de feature, se da el conflicto en local
- Resuelvo y subo el branch 'dev-conflict'
- Creo el PR y no hay conflictos ahora.
- Luego confirmo en el otro PR, ya está cerrado
Resultado: Muchos pasos pero bastante seguro y mantengo el mismo flujo de trabajo.
Conclusión
Ambas estrategias al parecer tienen el mismo resultado, pero dependiendo del caso elegiré cuál es mejor. El criterio imagino será que tanto quiero cuidar el historial git.
De hecho aún falta algunos puntos por evaluar como el git rebase.
Blooper
Al pasar de la estrategia 1 a la estrategia 2, no borre los branches por lo tanto el branch feature 2 me termino dando conflicto hahaha ..