¿Qué es un pull request?

En esta entrada, la tercera de una serie de tres, explicamos qué es un pull request y cómo funciona en github.

Recordamos brevemente qué es lo que nuestros usuarios aalbagarcia y aprendegit-user1 hicieron en las dos entradas anteriores:

  • El usuario aalbagarcia crea un repositorio en github: https://github.com/aprendegit/fork
  • El usuario aprendegit-user1 crea un fork (bifurcación) para trabajar en él: https://github.com/aprendegit-user1/fork
  • Los dos usuarios realizan modificaciones cada uno en su repositorio, cada uno de ellos hace un commit y posteriormente un push. Cada uno sube los cambios a su correspondiente repositorio
  • El usuario aprendegit-user1 configura un repositorio remoto adicional (upstream) e incorpora, haciendo un merge, los cambios en el código que hizo aalbagarcia. Después de hacer el merge, aprendegit-user1 hace un push para actualizar su repositorio remoto.

Lo último que nos falta por hacer es que el usuario aalbagarcia, que es el propietario del repositorio inicial (https://github.com/aprendegit/fork), incorpore el trabajo del usuario aprendegit-user1 que se encuentra en el fork https://github.com/aprendegit-user1/fork.

¿Qué es un pull request?

Un pull request es una petición que el propietario de un fork de un repositorio hace al propietario del repositorio original para que este último incorpore los commits que están en el fork. En el caso que nos ocupa, el usuario aprendegit-user1 le enviará la petición a aalbagarcia para que este último incorpore los commits que tiene en su fork.

Lo primero que hará el usuario aprendegit-user1 será crear una rama que apuntará al último commit que ha hecho y que contiene las modificaciones a la página de inicio. El procedimiento es el de siempre:Creando una rama antes de hacer el pull request

  • Se selecciona a la izquierda la rama master y se hace clic sobre el último commit de la rama
  • Se hace click sobre el icono “Branch”
  • Se introduce el nombre de la rama, en este maso mycommits
  • Se hace clic sobre “Create Branch”

Si se usa la línea de comandos, la secuencia sería:

$ git checkout master
Switched to branch 'master'
$ git checkout -b mycommits
Switched to a new branch 'mycommits'

Una vez creada la rama, el usuario aprendegit-user1 hace push de la rama “mycommits” a su fork:

  • Se selecciona la rama mycommits a la izquierda asegurándonos de que esta queda como rama activa haciendo doble clic sobre ella
  • Se selecciona el último commit de la rama
  • Se hace clic sobre el icono Push de la bara de herramientas
  • En el desplegable, se selecciona en la columna “Push?” la rama mycommits y se marca en la columna de la derecha (Track) la rama local como tracking branch.
  • Se hace clic sobre OK.
La secuencia de comandos sería 
$ git checkout mycommits
$ git push -u origin mycommits
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:aprendegit-user1/fork
    * [new branch] mycommits -> mycommits
Branch mycommits set up to track remote branch mycommits from origin.

Al terminar, el estado del repositorio es el siguiente:

Solicitando el pull request

En este momento, el usuario aprendegit-user1 accede a su cuenta de github y abre en su navegador la página de su fork https://github.com/aprendegit-user1/fork.

Una vez hemos accedido, cambiamos a la rama mycommits como se indica en la siguiente captura:Acceder a github y cambiar a la rama mycommits

Una vez se ha cambiado a la rama mycommits, aprendegit-user1 hace clic sobre el botón “Pull Request”El botón pull request

Esta es la pantalla que se presenta a aprendegit-user1:Pantalla para enviar el pull request

En la parte superior, aprendegit-user1 selecciona la rama que contiene los commits que aalbagarcia (el destinatario del pull request) debe incorporar en su repositorio. En la parte de abajo se ven tres pestañas en las que se puede:

  • Poner un título y descripción al pull request
  • Ver los commits que aalbagarcia incorporará al repositorio si acepta el pull request (pestaña Commits)
  • Ver un diff que los cambios que se incluyen en los commits (pestaña Files Changed)

Es una buena práctica poner un título y descripción que reflejen el motivo del commit. Estos pull requests los ven todos los colaboradores del proyecto (si el proyecto es público lo ve todo el mundo) Así que aunque aalbagarcia y aprendegit-user1 hayan hablado por teléfono acerca de este pull request, el resto del mundo seguramente no ha escuchado la conversación. Pensando en el resto del equipo, aprendegit-user1 incluye un mensaje descriptivo de qué contiene el pull request. Cuando termina, hace clic sobre el botón “Send Pull Request”. Esta es la pantalla a la que aprendegit-user1 llega después de enviarlo:Pantalla del pull request que ve aprendegit-user1

La captura es bastante sencilla de entender. Vemos el título y descripción introducidos por aprendegit-user1, los commits y una interfaz para intercambiar comentarios con el equipo.

Aunque en pequeño, se nos indica qué es lo que tendríamos que hacer para añadir commits a este pull request: enviar más commits a la rama “mycommits” del fork de aprendegit-user1.

¿Porqué podemos necesitar añadir más commits? Imagínate que el equipo revisa el pull request y se determina que todavía queda trabajo pendiente de hacer. ¿Cómo se procede? aprendegit-user1 continúa el trabajo en la rama rama “mycommits” de su fork y cuando termina lo sube a su repositorio remoto. El pull request se actualiza y todo el equipo puede ver el nuevo código. Esto lo veremos en detalle en otro artículo, de momento, seguimos con el proceso.

Aceptando el pull request

Cuando aprendegit-user1 envía el pull request, Github envía al propietario un email avisándole de que tiene un pull request listo para revisar. En este caso, el usuario aalbagarcia recibe el email, accede a su cuenta de Github y va a su repositorio https://github.com/aprendegit/fork:Página del propietario del repositorio después del pull request

En esta pantalla, seleccionamos la pestaña “Pull Requests” y accedemos a una interfaz que nos muestra todos los que tenemos. Dado que este es el primero, en este listado seleccionamos el único que hay:Listado de pull requests del repositorio

Cuando aalbagarcia selecciona “Añadiendo logotipo”, accede a una pantalla muy parecida a la que hemos visto con el usuario aprendegit-user1. En la siguiente captura indico cuáles son las diferencias:La página del pull request vista por el propietario

Las diferencias son:

  • Existe un botón “Merge pull request” que el propietario aalbagarcia utilizará para incorporar los commits al repositorio
  • Existe un botón “Close” que el propietario utiliza para cerrar el pull request sin incorporar los cambios

Una vez revisado el código y confirmado que todo está bien, aalbagarcia hace clic sobre el botón “Merge Pull Request”. En ese momento Github le pedirá que introduzca un comentario para el merge commit. Una vez introducido, aalbagarcia hace clic sobre el botón “Commit merge” y ya está, Github automáticamente cierra el pull request. También envía un email a los dos interesados (aalbagarcia y aprendegit-user1) avisándoles de que se han incorporado los cambios en el repositorio.

Si volvéis a la página de commits del repositorio en github (https://github.com/aprendegit/fork/commits/master) veréis que tras hacer el pull request, aparece un nuevo commit en el repositorio:Merge commit tras el pull request

¿Cómo quedan los repositorios de aalbagarcia y aprendegit-user1?

En este momento, el repositorio remoto de aalbagarcia ya contiene el merge commit que se ha creado a través del pull request. La pregunta es ¿el de aprendegit-user1 también? ¿verán estos nuevos commits los dos usuarios?

…la respuesta es que, efectivamente, no lo verán hasta que hagan un fetch en sus respetivos repositorios. Tras hacer los dos usuarios un fetch de todos sus repositorios remotos (recuerda que aprendegit-user1 tiene 2 remotos,  origin y upstream) así quedan sus respectivas copias de trabajo:

Copias de trabajo después del pull request y el fetch

Para terminar:

  • aalbagarcia tiene que hacer un merge de la rama origin/master a la rama master
  • aprendegit-user1 tiene que hacer un merge de la rama upstream/master a la rama master y después hacer un push de su rama master

Una vez hecho esto, los repositorios quedan de la siguiente manera:

Copias de trabajo después de macer merge de las ramas remotas

Y como podéis ver, están sincronizados.

¿Quieres hace un pull request?

Si quieres hacer tú mismo el proceso para ver cómo funciona, ve al repositorio https://github.com/aprendegit/fork, haz un fork y envíanos las modificaciones siguiendo los pasos que hemos seguido en esta serie de artículos. Si tienes alguna duda no dudes en preguntarnos.

Seguiremos hablando de pull requests, aunque eso ya será en otros artículos.

27 pensamientos en “¿Qué es un pull request?

  1. Pingback: Mantener tu fork al día | Aprende GIT

  2. Pingback: Uso avanzado de referencias: github y pull requests | Aprende GIT

  3. Eric

    Como no veo comentarios, por mi parte decir que se ha entendido todo perfectamente, una explicación muy clara, gracias.

    Responder
  4. Sandino

    Muchas gracias por compartir tu experiencia y tiempo con este tutorial, me fue muy fácil seguirlo está bien explicado y me sirvió para hacer mi primer pull request a un repo al que quería compartir un cambio, gracias saludos sigue así

    Responder
    1. alfonso

      Hola Sandino:

      Gracias por tu comentario. Me alegra mucho que el artículo te haya ayudado.

      Un saludo,

      Alfonso

      Responder
  5. Luis

    Pues yo no entendí mucho, imagino porque soy nuevo en Git y no me familiarizo aun con los terminos:
    “fork”, “bifurcacion”, “pull request”, “checkout”

    Responder
  6. Lucas

    Hola,
    Primero que nada muy útil el tutorial.
    Particularmente en mi proyecto, tendría que tener una funcionalidad puntual
    y consiste en que los pull request los pueda validar mas de un usuario. esto es posible?
    Básicamente lo que solicita el cliente, es un usuario de ellos que simplemente tenga la función de validar los pull request y confirmar los cambios.
    Esto se puede manejar?

    Gracias.

    Saludos.

    Responder
    1. alfonso

      Hola Lucas:

      En primer lugar, gracias por tus comentarios.

      Sobre lo que planteas, creo que no lo vas a poder conseguir con la versión estándar de github. Si miras aquí https://help.github.com/articles/permission-levels-for-an-organization-repository, lo máximo que podrías crear es un usuario administrador de vuestro repositorio que tenga permiso de escritura lo que le permitiría, entre otras cosas, aprobar / rechazar pull requests. Sin embargo, este podría hacer todas las operaciones de escritura que tienes en ese enlace.

      También puedes echar un vistazo a la documentación de bitbucket: https://confluence.atlassian.com/display/BITBUCKET/Repository+privacy,+permissions,+and+more
      aunque echando un vistazo rápido me ha parecido que vas a tener qué implementar una solución parecida a la de github que te he puesto arriba.

      Otra solución que puedes mirar el gitlab, aunque he estado mirando en los permisos que facilita y no indica al respecto (https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/permissions/permissions.md)

      Tendrías que mirar si la versión Github Enterprise o Stash (de bitbucket) os permite hacer lo que estás planteando.

      Responder
  7. Lucas

    Otra consulta.
    Nosotros en el proyecto utilizamos eclipse y tenemos el remoto en la red interna del cliente.
    Como se gestionan los pull request para ver las modificaciones.
    Se puede ver los cambios y demas desde el mismo eclipse? hay algún programa que cumpla la función de la interfaz del servidor gitHub?

    Gracias.

    Saludos.

    Responder
    1. alfonso

      Hola Lucas:

      El servidor del cliente ¿qué tipo de servidor es? ¿cómo os conectáis a el para hacer los push/pull? ¿Usan gitlab, github enterprise, stash, teamforge o ssh puro y duro?

      Con respecto a la última pregunta “¿hay algún programa que cumpla la función de la interfaz del servidor gitHub?”: la solución que te recomendaría que mirases es gitlab.

      Responder
  8. Miguel Ángel Rojas Coraje

    Hola alfonso,

    Primero agradecerte por estos tutoriales tan buenos que haz montado en esta página. Tengo un problema, estoy intentando hacer otro pull request desde la rama “mycommits” que se creo en este ejemplo y no puedo, al agregar otro archivo a mi repositorio local siguiendo los pasos :

    git add “miFichero”
    Luego
    git commit -m “Nuevo commit”
    Luego
    git push origin master
    Y por último quisiera hacer otro pull request hacia el repositorio original pero con la misma rama(mycommits)
    pero me aparece un mensaje diciéndome que no hay nada para enviar.
    git push -u origin mycommits

    Entonces, he creado otra rama para poder hacer otro pull request y si me funciono. Ahi está mi duda :
    Es necesario crear ramas para cada commit que se pretender enviar al repositorio original?

    Saludos

    Responder
    1. alfonso

      Hola Miguel Ángel:

      Gracias por el feedback y por tu comentario.

      Primera pregunta

      Tengo la impresión de que estás haciendo push de la rama que no es. Según me cuentas has hecho los commits a la rama “mycommits”, sin embargo, el comando push que estás utilizando es

      # git push origin master

      Para enviar un pull request de la rama “mycommits” debes subir esa rama a github lo que significa de debes hacer push de esa rama:

      # git checkout mycommits
      # git push origin mycommits

      (si quieres crear a la vez un tracking brach puedes utilizar el comando git push -u origin mastersmycommits)

      Segunda pregunta

      Si ya hiciste un pull request de la rama “mycommits” y ese pull request está abierto… no creo que sea buena idea hacer otro pull request de esa misma rama, dependiendo de la situación puede que no tenga sentido. Lo que se suele hacer en estos casos es enviar los commits nuevos a tu rama remota “mycommits”. Github automáticamente los detecta y los pone en el pull request que ya estaba creado. De esta forma se puede hacer code review e ir mejorando el código antes de incorporarlo.

      Si me envías un pull request al repositorio “fork” que he creado, verás que no te aceptaré el pull request hasta que hagas exactamente lo que me estás preguntando (si miras en el repo mío verás varios pull request que no están cerrados por que no me enviaron un segundo commit 😉 ).

      Sobre lo que comentas de que al hacer “git push origin mycommits” te dice que no hay nada que enviar ¿en qué rama estás? ¿es “mycommits” la rama activa”? si es así, comprueba que los commits los hiciste en esa rama y no en otra por error (suele ser uno de los motivos más habituales de ese mensaje que te está saliendo).

      Un saludo,

      Alfonso

      Responder
  9. Pingback: Colaborando con el software libre, CakePHP | proavan

  10. Ernesto

    Entiendo la idea de crear un fork para colaborar con otro proyecto pero me podrías explicar en que se diferencia de clonar el proyecto, crear un branch, hacer los cambios en este branch y luego hacer un pull request para que el propietario del proyecto original haga un merge e incorpore los cambios al proyecto?
    Es decir, ¿Por qué hacerlo con un fork y no con un branch?

    Responder
  11. Ivan Ferrer

    Gracias. Muy aclarador, no es fácil con tantos términos.
    Entiendo que el hecho de crear el repositorio Upstream desde el cual pedir el Pull Request es para que en el repositorio original no aparezcan todos los commits “viejos” del usuario, no? Es decir, para mandar una copia limpia con un solo commit (si no hay más cambios luego).
    Saludos.

    Responder
  12. Rene

    Genial, no se como he perdido todo mi tiempo estos ultimos años usando SVN. Muchas gracias, gran aporte

    Responder
  13. Pingback: Mejora tu código en 5 pasos - Testeando Software

  14. Pingback: ¿Cómo puede ayudarnos Github con sus nuevas funcionalidad para trabajar en equipo? | Esther Claravalls

  15. Pingback: ¿Cómo puede ayudarnos Github con sus nuevas funcionalidades a trabajar en equipo? – Educacion IT

  16. Pingback: Aprendiendo a aprender – Ciencia Moe

  17. Pingback: Librerías Arduino | Aprendiendo Arduino

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *