Estrategias para resolver conflictos en git

Comparo dos estrategias al resolver confictos en git

hace 3 meses   •   5 min de lectura

Por Andrés Tuñón
Tabla de contenidos

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í:

Base del proyecto
Base del proyecto

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:

creación de los branches
creación de los branches

A continuación una representación gráfica del flujo que estoy buscando crear:

Representación gráfica
Representación gráfica

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:

feature branch
feature branch

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:

feature2 -> development
feature2 -> development https://github.com/ngxCoder/gitconflict/pull/1

Replicando la actualización a mi branch local el jueves

Me coloco en el branch feature y hago pull desde origin/development:

pull desde origin development
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.

Resolución del conflicto
Resolución del conflicto

Ahora armo el PR por si ocurre algo extraño:

PR con el conflicto resuelto
PR con el conflicto resuelto

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:

Representación gráfica de la estrategia 1
Representación gráfica de la estrategia 1

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.

feature2 -> development
feature2 -> development https://github.com/ngxCoder/gitconflict/pull/4

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)

conflicto en el PR
conflicto en el PR
punto donde se genera el conflicto
punto donde se genera el conflicto

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
git merge feature
git merge feature
  • Resuelvo y subo el branch 'dev-conflict'
  • Creo el PR y no hay conflictos ahora.
comparando dev-conflict
comparando dev-conflict
  • 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 ..

feat(index.html): add wrong message by ngxCoder · Pull Request #3 · ngxCoder/gitconflict
Contribute to ngxCoder/gitconflict development by creating an account on GitHub.

Corre la voz