Skip to content
This page has been auto-translated and may contain errors.View in English

El flujo de pull requests ​

docs.scrimba.com

Has estado trabajando en una función en tu propia rama y ya está lista. El proyecto es compartido: otras personas también hacen commits en él, así que no vas a hacer push directo a main y esperar que todo salga bien. Quieres que revisen el cambio, que se discuta si hace falta, y que se fusione de una manera que el resto del equipo pueda ver. Todo ese camino, desde una rama en tu máquina hasta que el código llega a main, es el flujo de pull requests, y así es como casi todos los equipos en GitHub integran sus cambios. La parte de Git solo usa comandos de capítulos anteriores: una rama, un commit y un push:

bash
$ git switch -c add-five-day-forecast
Switched to a new branch 'add-five-day-forecast'
$ git add src/forecast.js
$ git commit -m "Add five-day forecast panel"
$ git push -u origin add-five-day-forecast
Branch 'add-five-day-forecast' set up to track 'origin/add-five-day-forecast'.

Ese push envía tu rama a GitHub. Todavía no se ha fusionado nada, y ni siquiera se ha propuesto nada para revisión. El siguiente paso, abrir el pull request, ocurre en el sitio web de GitHub.

Qué pasa cuando abres un pull request ​

En GitHub, después de un push como el anterior, normalmente vas a ver un banner que te ofrece comparar tu nueva rama contra main. Haz clic ahí, escribe un título y una breve descripción de qué cambió y por qué, y abre la página que se crea. Esa página es un pull request, muchas veces abreviado como PR: una solicitud para fusionar una rama en otra, con una conversación asociada.

Un pull request propone una fusión y espera aprobación. Alguien, quizás tú, quizás un compañero de equipo, lee el cambio, deja comentarios, y solo lo fusiona una vez que se ve bien. Hasta que eso pase, tu rama y main se quedan exactamente como estaban antes de que abrieras la página.

No tienes que esperar a que una función esté terminada para abrir el PR. Muchos equipos abren uno temprano y lo marcan como borrador (draft), lo cual indica "todavía no está listo para revisión" y a la vez le da a los revisores un lugar donde comentar sobre el rumbo antes de que el trabajo esté terminado. Una buena descripción enlaza cualquier issue relacionado y dice qué probaste, para que un revisor no tenga que reconstruir eso solo a partir del diff.

GitHub mantiene una ref para cada pull request en el remoto, incluso antes de que agregues la rama del PR a tu propio repositorio: refs/pull/<number>/head. Puedes traerla (fetch) directamente para revisar el PR de un compañero de equipo en tu máquina, sin tener que agregar su fork como remoto primero.

bash
$ git fetch origin pull/42/head:pr-42
From github.com:mara-chen/weather-app
 * [new ref]         refs/pull/42/head -> pr-42
$ git switch pr-42
Switched to branch 'pr-42'

Ahora pr-42 es una rama local real construida a partir del pull request número 42, lista para correr y probar antes de que dejes un solo comentario.

JunoQué pasa cuando abres un pull request Un pull request es una solicitud para fusionar tu rama en otra, que se abre en GitHub después de que haces push. Alguien revisa el cambio primero, y solo después se fusiona. El ciclo de todos los días es: rama, push, abrir un pull request, recibir revisión, fusionar.
JunoQué pasa cuando abres un pull request Un PR propone una fusión y sostiene la conversación alrededor de ella, y puedes abrir uno temprano como borrador para recibir retroalimentación antes de terminar el trabajo. Escribe la descripción pensando en que un revisor de verdad la va a leer: qué cambió, por qué, y qué probaste.
JunoQué pasa cuando abres un pull request GitHub mantiene una ref oculta para cada pull request, refs/pull/<number>/head, así que puedes traer el PR de un compañero de equipo directo a tu máquina con git fetch origin pull/42/head:pr-42 en vez de agregar su fork como remoto. Prueba el cambio localmente antes de dejar tu primer comentario.

Fork vs. rama ​

Abrir un pull request desde una rama funciona cuando tienes acceso de escritura al repositorio, que es el caso normal en los proyectos de tu propio equipo. Contribuir a un proyecto al que no tienes acceso de escritura requiere un paso extra: un fork, tu propia copia del repositorio bajo tu propia cuenta de GitHub.

Creas ramas y haces commits dentro de tu fork exactamente como lo harías en un proyecto propio, haces push a tu fork, y luego abres el pull request desde la rama de tu fork hacia el repositorio original. GitHub compara entre los dos repositorios de la misma manera en que compara dos ramas dentro de un solo repositorio, así que el flujo de revisión y fusión se ve igual en ambos casos.

Si planeas enviar más de un PR a un proyecto que has forkeado, vale la pena agregar el repositorio original como un segundo remoto, normalmente llamado upstream, mientras origin sigue apuntando a tu propio fork. Ejecuta git fetch upstream y fusiona upstream/main en tu rama para ponerte al día con un proyecto que ha avanzado desde que hiciste el fork, siguiendo los mismos pasos que cubre el capítulo Remotos y GitHub para cualquier remoto.

JunoFork vs. rama Crea una rama directamente cuando tienes acceso de escritura a un repositorio, como en los proyectos de tu propio equipo. Haz un fork cuando no lo tienes: un fork es tu propia copia del repositorio de otra persona, y creas ramas y haces push dentro de esa copia antes de abrir el pull request de vuelta hacia el original.
JunoFork vs. rama Un fork es una copia completa de un repositorio bajo tu cuenta, que se usa para contribuir donde no tienes acceso de escritura. Creas ramas, haces commits y haces push dentro de tu fork como de costumbre, y GitHub compara la rama de tu fork contra el repositorio original de la misma manera en que compara dos ramas dentro de un solo proyecto.
JunoFork vs. rama Mantén dos remotos en un proyecto forkeado: origin para tu propio fork, upstream para el repositorio original, así puedes traer y fusionar sus cambios a medida que avanza. El PR en sí sigue comparando la rama de tu fork contra la rama base del repositorio original.

Lograr que tu pull request pase la revisión ​

Una vez que un PR está abierto, se convierte en una conversación continua sobre el diff. Un revisor lee el cambio, deja comentarios en líneas específicas, y lo aprueba o solicita cambios. Cuando se solicitan cambios, sigue haciendo commits y push a la misma rama: cada push actualiza el mismo PR en vez de crear uno nuevo. Una vez que un revisor aprueba y pasan las verificaciones requeridas, el PR está listo para fusionarse.

GitHub registra una revisión en uno de tres estados: aprobado, cambios solicitados, o comentado (retroalimentación sin un veredicto definido). Responde a los comentarios a medida que los atiendes y marca la conversación como resuelta para que un revisor pueda ver de un vistazo qué queda pendiente. Si haces push de una corrección para un comentario específico, ayuda mencionarlo en tu mensaje de commit o en una respuesta, ya que un revisor que revisa un PR largo va a estar buscando exactamente eso.

Cuántas aprobaciones necesita un PR, y si cada hilo de comentarios tiene que marcarse como resuelto antes de que se habilite el botón de merge, suele ser una regla asociada a la rama base en sí en un proyecto bien organizado.

JunoLograr que tu pull request pase la revisión Un revisor comenta tu pull request y puede pedir cambios. Haz commits y push de más trabajo a la misma rama para atenderlos, y el PR se actualiza automáticamente. La fusión ocurre una vez que alguien aprueba.
JunoLograr que tu pull request pase la revisión Las revisiones quedan en uno de tres estados: aprobado, cambios solicitados, o comentado. Haz push de correcciones a la misma rama para actualizar el PR, responde a los comentarios a medida que los resuelves, y mantén orientado al revisor en un hilo largo.
JunoLograr que tu pull request pase la revisión Los estados de revisión determinan si se habilita el botón de merge, pero el criterio exacto, cuántas aprobaciones, si cada hilo de comentarios debe resolverse, suele ser una regla asociada a la rama base en sí en un proyecto bien organizado.

Por qué un pull request no se fusiona ​

A veces el botón de merge de un PR aparece deshabilitado, y GitHub muestra un mensaje en su lugar: "This branch has conflicts that must be resolved" o "This branch is out of date with the base branch". Ambos mensajes describen un estado normal y solucionable: main avanzó desde que creaste tu rama, normalmente porque el PR de otra persona se fusionó en el intervalo, y tu rama necesita ponerse al día antes de que GitHub pueda combinar las dos de forma limpia. Esto pasa en cualquier proyecto con más de un colaborador, así que hay que esperarlo en lugar de tenerle miedo.

Arréglalo localmente de la misma manera en que juntarías cualquier par de ramas:

bash
$ git switch add-five-day-forecast
$ git fetch origin
From github.com:mara-chen/weather-app
   9f8e7d6..b7c9e21  main       -> origin/main
$ git merge origin/main

Si no hay nada que se superponga, la fusión se completa sola y haces push, y el PR se actualiza y el botón se habilita. Si las mismas líneas cambiaron en ambos lados, Git marca el conflicto en el archivo para que lo resuelvas exactamente como se cubre en Fusiones y conflictos: abre el archivo, edita los marcadores de conflicto hasta llegar al resultado que quieres, luego usa git add y git commit para terminar la fusión, y vuelve a hacer push.

Un pull request atascado necesita ponerse al día o que se resuelva su conflicto.

En un PR que se queda abierto por más de un día o dos, vale la pena fusionar main en tu rama de tanto en tanto en vez de esperar a que el botón te bloquee. Una rama que está un día desactualizada normalmente se fusiona sin ningún conflicto; una que está tres semanas desactualizada tiene mucha más superficie para que dos cambios choquen en las mismas líneas. El propio botón "Update branch" de GitHub en la página del PR hace esa misma fusión por ti cuando no hay nada que resolver a mano.

Algunos equipos rebasan una rama de función sobre main en lugar de fusionarla, para mantener el historial final lineal en vez de mostrar un commit de merge por cada PR. Esa disyuntiva es la misma que se cubre en Fusiones y conflictos: rebasar reescribe los commits de tu rama, lo cual es seguro siempre y cuando seas la única persona con copias de ellos, así que una rama de función solitaria que solo vive en tu máquina y su PR es una candidata razonable. Rebasar una rama que otras personas ya han descargado y sobre la que ya construyeron trabajo no lo es, porque reescribe un historial del que dependen.

JunoPor qué un pull request no se fusiona Un botón de merge deshabilitado significa que tu rama está atrasada respecto a main o tiene un conflicto con ella. Nada está roto. Cambia a tu rama, haz fetch, y fusiona main en ella, resolviendo cualquier conflicto de la misma manera en que lo harías en cualquier otro caso, luego vuelve a hacer push.
JunoPor qué un pull request no se fusiona Fusiona main en una rama de larga duración de tanto en tanto en vez de esperar a que GitHub bloquee el botón de merge. Ponerse al día de forma más pequeña y frecuente significa conflictos más pequeños, y el botón "Update branch" de GitHub puede encargarse del caso sin conflicto por ti.
JunoPor qué un pull request no se fusiona Tanto fusionar como rebasar tu rama sobre main arreglan un PR atascado, y una rama de función solitaria es segura de rebasar porque nadie más tiene una copia de sus commits. En cuanto otras personas hayan descargado una rama, quédate con fusionarla en vez de rebasarla.

Qué es un pull request en realidad ​

Un pull request no es un objeto de Git, y no existe ningún comando de git que cree uno. Git y GitHub no son lo mismo: Git solo conoce commits, ramas y otras refs (una ref es un nombre que apunta a un commit). GitHub construye toda la página del PR, los comentarios y el botón de merge sobre dos refs que compara: tu rama (la head) y la rama a la que te estás fusionando (la base, normalmente main). Esa comparación es la razón por la que abres un pull request en el sitio web de GitHub (o mediante la propia herramienta de línea de comandos o API de GitHub), y nunca con un simple comando de git.

Como un PR vive en GitHub, separado del historial del repositorio, sus comentarios y la conversación de revisión no viajan con los commits. Si algún día migras un proyecto a un host diferente, cada commit te acompaña sin cambios, pero los pull requests y sus discusiones se quedan atrás en GitHub, porque nunca formaron parte de los datos de Git en primer lugar.

GitHub calcula el diff de un PR encontrando la base de fusión (merge base), el commit más reciente que comparten tanto la ref head como la ref base, y comparando la head contra ese punto en vez de contra como se ve main en este momento. Cada push a la rama agrega una versión nueva al mismo PR en vez de crear una comparación nueva. La protección de ramas (branch protection) es la capa de políticas que se sienta sobre todo esto: una regla que tú (o tu organización) asocian a una rama, casi siempre main, que puede exigir que pasen verificaciones de estado, exigir un número mínimo de revisiones aprobatorias, y bloquear los push directos para que todo cambio se vea forzado a pasar por un pull request. Git en sí mismo no impone nada de esto. Te va a dejar hacer push directo a main desde tu terminal sin problema, hasta que la regla de GitHub rechace la solicitud.

JunoQué es un pull request en realidad Un pull request es una función de GitHub construida sobre Git: Git registra commits y ramas, y GitHub agrega la página del PR y el botón de merge comparando dos de ellos. Mantener a Git y GitHub separados en tu cabeza explica gran parte de lo que, si no, parecería magia.
JunoQué es un pull request en realidad Un PR compara tu rama contra una rama base y vive por completo en GitHub, así que sus comentarios e historial de revisión no se mueven si el repositorio alguna vez cambia de host. Los commits en sí son la única parte que realmente pertenece a Git.
JunoQué es un pull request en realidad Un PR es GitHub comparando una ref head contra una ref base a partir de su base de fusión compartida, actualizada con cada push. La protección de ramas es la política aplicada por encima de eso, que exige verificaciones o revisiones antes de fusionar. Git en sí mismo no impone nada de esto: te va a dejar hacer push directo a main hasta que la regla de GitHub lo detenga.