Veamos un flujo de trabajo con Git para gestionar y aprobar un Pull Request (PR) en un repositorio remoto compartido. El flujo de trabajo se ha comprobado que funciona correctamente en repositorios remotos gestionados en Bitbucket.
Suponemos un equipo formado por 3 desarrolladores (Ana, Lucía y Carlos) que están trabajando sobre un repositorio compartido utilizando el flujo de trabajo denominado Gitflow (ver el post de Vicent Driessen). En la rama develop
se integran las features que se van desarrollando en ramas independientes.
Se ha definido la política de que antes de integrar una rama de característica se debe realizar un Pull Request en Bitbucket y algún otro miembro del equipo debe comprobar su funcionamiento y dar el visto bueno. La integración la realizará el mismo desarrollador que ha creado el Pull Request. Aunque Bitbucket proporciona la opción de cerrar el PR desde la interfaz web, utilizaremos comandos Git en el repositorio local para hacerlo.
Un ejemplo del flujo de trabajo:
-
Ana abre una feature creando la rama
feature10
, la sube a Bitbucket, realiza commits y cuando termina la característica comprueba que la rama se mezcla bien endevelop
y crea un PR en Bitbucket. -
Lucía revisa el PR, se da cuenta de que faltan un par de cambios y pide a Ana que los termine.
-
Ana realiza los cambios en la rama, realiza la integración en
develop
y cierra el PR. -
Lucía y Carlos actualizan sus repositorios locales.
Comandos Git para implementar este flujo de trabajo:
1. Ana abre la feature y crea el PR en Bitbucket
$ git checkout -b feature10
$ git push -u origin feature10
# Hace cambios y commits y los sube al repositorio
$ git add .
$ git commit -m "Cambio"
$ git push
# Comprueba que el merge con develop funciona bien
$ git checkout develop
$ git pull
$ git merge feature10
# Si el merge es OK, se crea el PR en Bitbucket
<Se crea el PR en Bitbucket>
# Se deshace el merge
$ git reset --merge ORIG_HEAD
# Y se cambia a la rama a la espera de que un compañero apruebe el PR
$ git checkout feature10
Si el merge en develop
genera un conflicto (o bien ficheros en conflicto, o tests que no pasan), se deshace el merge, se añaden cambios en la rama feature10
para evitar los conflictos y se vuelve a probar el merge con develop. La idea es asegurarse de que en el momento de hacer el PR no existe ningún conflicto entre la rama y develop
.
# Si el merge en develop no es OK
# Se deshace el merge
$ git reset --merge ORIG_HEAD
$ git checkout feature10
# Se hacen los cambios para arreglar los conflictos
$ git add .
$ git commit -m "Arreglados conflictos con develop"
# Se suben los cambios
$ git push
# Y se crea el PR después de comprobar que la integración con develop será OK
$ git checkout develop
$ git merge feature10
# Si el merge es OK, se crea el PR en Bitbucket
<Se crea el PR en Bitbucket>
# Se deshace el merge
$ git reset --merge ORIG_HEAD
# Y se cambia a la rama a la espera de que un compañero apruebe el PR
$ git checkout feature10
2. Lucía revisa el PR y pide cambios
$ git pull
$ git checkout feature10
$ git checkout develop
$ git merge feature10
# Comprueba el merge y se da cuenta de que faltan
# un par de cambios, que pide en la interfaz de Bitbucket.
# Deshace el merge para volver develop al commit anterior
$ git reset --merge ORIG_HEAD
3. Ana añade los cambios en la rama y cierra el PR
$ git checkout feature10
# Añade los cambios
$ git add .
$ git commit -m "Cambios añadidos"
$ git push
# El push actualiza el PR en Bitbucket, y los compañeros pueden ver los nuevos cambios
# Cuando todo está OK, se cierra el PR (supongamos que es el número 21)
$ git checkout develop
$ git merge --no-ff -m "Integrado PR (pull request #21)" feature10
# La cadena `pull request #21` aparecerá en lal web de Bitbucket como un enlace a la página del PR
# Sube el merge a Bitbucket y esto cierra el PR
$ git push
# Se borra la rama en remoto y en local
$ git push --delete origin feature10
$ git branch -d feature10
4. Lucía y Carlos actualizan sus repositorios
$ git checkout develop
$ git pull
# Si se han bajado la rama feature10 tienen que borrarla en local y borrar la referencia remota
$ git branch -d feature10
$ git remote prune origin
Una cuestión: ¿es preciso tener las mismas ramas en local que en remoto, si es así, deben estar sincronizadas?. Cuando voy a hacer un merge al master en mi local de una rama creada previamente, ¿debo antes hacer un pull por si otros han modificado la rama master?