Capítulo 20 de 33 10 secciones 7 min

Proponer un cambio en el proyecto de otra persona

Qué es un fork, qué es un pull request y por qué no da miedo

<strong>Un pull request es pedirle a alguien que se lleve tus commits a su proyecto.</strong> El camino son cuatro pasos: bifurcas el proyecto (fork, que es tu copia en GitHub), lo clonas, haces tus cambios <strong>en una rama nueva</strong> y la subes. GitHub detecta la rama y ofrece el botón para abrir la propuesta. Lo único que se hace obligatoriamente en la web es ese último clic; todo lo demás es Git del que ya sabes.

Aquí es donde Git deja de ser una herramienta personal. Un pull request es la forma en que millones de personas mejoran proyectos que no son suyos, y también es la forma en que trabaja cualquier equipo por dentro 🤝

Y la palabra asusta más que la cosa. Traducida es: "te dejé unos cambios listos, ¿te los llevas?".

Fork y clone no son lo mismo

ForkClone
Dónde queda la copiaEn tu cuenta de GitHubEn tu computadora
Es deGitHub, no de GitGit
Puedes subir cambiosSí, es tuyaSolo si tienes permiso en el original
Para quéProponer cambios en algo ajenoTrabajar en tu máquina

El orden real es: fork primero, clone después. Clonas tu copia, no la original 🍴

Los cuatro pasos, con la parte de Git ejecutada

El fork es un botón en GitHub. Todo lo demás es esto, y lo vamos a hacer con el servidor de práctica del capítulo 12: uno hace de proyecto original y otro de tu bifurcación.

mkdir original
cd original
git init -q
printf 'ciudad,monto\nLima,1200\nArequipa,890\n' > ventas.csv
printf '# Ventas por ciudad\n' > README.md
git add .
git commit -q -m "Primera version del reporte de ventas"
cd ..
git clone -q --bare original original-servidor.git
git clone -q --bare original mi-fork.git
git clone -q mi-fork.git mi-copia
cd mi-copia
git remote add upstream ../original-servidor.git
git remote -v
origin	/home/miss-yera/mi-fork.git (fetch)
origin	/home/miss-yera/mi-fork.git (push)
upstream	../original-servidor.git (fetch)
upstream	../original-servidor.git (push)

Dos remotos y esto es la costumbre del mundo entero: origin es tu bifurcación, donde sí puedes subir, y upstream es el proyecto original, de donde traes las novedades 🔀

Una rama por propuesta

Este es el paso que la gente se salta y el que más problemas causa después:

git switch -q -c agrega-cusco
printf 'Cusco,760\n' >> ventas.csv
git add ventas.csv
git commit -q -m "Se agregan las ventas de Cusco"
git branch
git log --oneline
* agrega-cusco
  main
ef5f2ea Se agregan las ventas de Cusco
b566789 Primera version del reporte de ventas

El nombre de la rama importa porque va a ser el título por defecto de tu propuesta. agrega-cusco se entiende; cambios o arreglo2 no 🏷️

Subirla a tu bifurcación

git push -q -u origin agrega-cusco
git ls-remote --heads origin
ef5f2eae2ffecc668ba6580b0ab2be76c29de0ef	refs/heads/agrega-cusco
b56678907174a8d5cecfb72ae67a3e90a2f1beb6	refs/heads/main

Ahí está tu rama en tu copia de GitHub. Al entrar a la web te va a salir sola una barra amarilla que dice "Compare & pull request". Ese es el único clic obligatorio del capítulo 🖱️

Qué escribir en la propuesta

Tres cosas, cortas:

  • Qué cambia, en una frase.
  • Por qué, sobre todo si no es obvio.
  • Cómo comprobarlo, si hace falta ejecutar algo.

Y si el proyecto tiene un archivo CONTRIBUTING.md, léelo antes. Ahí está lo que quien mantiene el proyecto ya se cansó de repetir.

Ver exactamente lo que estás proponiendo

Antes de abrir el pull request conviene mirar tu propio cambio con los ojos de quien lo va a revisar:

git diff main..agrega-cusco
git log --oneline main..agrega-cusco
diff --git a/ventas.csv b/ventas.csv
index 0c80877..7a40551 100644
--- a/ventas.csv
+++ b/ventas.csv
@@ -1,3 +1,4 @@
 ciudad,monto
 Lima,1200
 Arequipa,890
+Cusco,760
ef5f2ea Se agregan las ventas de Cusco

Eso, exactamente eso, es lo que va a ver la otra persona. Si ahí aparece algo que no querías mandar, ahora es el momento 👀

Cuando el original avanza mientras esperas

Los pull requests tardan. Mientras tanto el proyecto sigue, y hay que traer lo nuevo para que tu propuesta no envejezca:

cd ../original
printf 'Trujillo,1450\n' >> ventas.csv
git add ventas.csv
git commit -q -m "Entran las ventas de Trujillo"
git push -q ../original-servidor.git main
cd ../mi-copia
git fetch -q upstream
git switch -q main
git merge -q upstream/main
cat ventas.csv
git log --oneline
ciudad,monto
Lima,1200
Arequipa,890
Trujillo,1450
c0dd365 Entran las ventas de Trujillo
b566789 Primera version del reporte de ventas

fetch trae sin mezclar, merge mezcla. Tu main vuelve a estar al día con el original 🔄

La trampa

Quieres proponer un arreglo en un proyecto ajeno. Lo bifurcas, clonas, arreglas el CSV de ventas ahí mismo y abres el pull request.

$ git branch
* main

$ git commit -am "Se corrige el monto de Lima"
$ git push origin main

# y al dia siguiente, otro arreglo distinto...
$ git commit -am "Se agrega Chiclayo"
$ git push origin main
Qué está mal

Los dos cambios están dentro del mismo pull request 🙃

Un pull request no es una lista de commits que tú eliges: es todo lo que tenga esa rama. Si trabajas en main, cada cosa nueva que subas se mete sola en la propuesta abierta, aunque no tenga nada que ver.

Quien revisa se encuentra un arreglo de un monto mezclado con una ciudad nueva y no puede aceptar uno sin el otro. Casi siempre acaba pidiendo que lo separes, o sea que el atajo costó más tiempo.

La costumbre: una rama por propuesta, con nombre de lo que hace, y main se queda limpia para poder empezar la siguiente desde ahí.

Comprueba que se entendió

Comprueba que lo tienes

Vas a proponer un arreglo en un proyecto que no es tuyo. ¿Dónde haces el commit?

  • En main de mi bifurcación
  • En una rama nueva de mi bifurcación
  • En main del proyecto original
  • Da igual, el pull request los separa

Ejercicios

1. Monta el original y tu bifurcación

Crea el proyecto del catálogo de bodegas, publícalo y haz tu copia.

cd ..
mkdir catalogo
cd catalogo
git init -q
printf 'bodega,ciudad\nBodega Inti,Cusco\n' > bodegas.csv
git add bodegas.csv
git commit -q -m "Catalogo inicial de bodegas"
cd ..
git clone -q --bare catalogo catalogo-servidor.git
git clone -q --bare catalogo fork-bodegas.git
git clone -q fork-bodegas.git trabajo
cd trabajo
git remote add upstream ../catalogo-servidor.git
git remote -v
origin	/home/miss-yera/fork-bodegas.git (fetch)
origin	/home/miss-yera/fork-bodegas.git (push)
upstream	../catalogo-servidor.git (fetch)
upstream	../catalogo-servidor.git (push)

origin es tuyo, upstream es de la otra persona.

2. Crea la rama de tu propuesta

Una rama con nombre de lo que hace.

git switch -q -c agrega-minimarkets
printf 'Minimarket Sol,Trujillo\n' >> bodegas.csv
git add bodegas.csv
git commit -q -m "Se agrega el minimarket de Trujillo"
git branch
* agrega-minimarkets
  main

El asterisco marca dónde estás parada.

3. Mira lo que vas a proponer

El diff contra main es exactamente lo que verá quien revise.

git diff main..agrega-minimarkets
diff --git a/bodegas.csv b/bodegas.csv
index 9fe9605..d3027d2 100644
--- a/bodegas.csv
+++ b/bodegas.csv
@@ -1,2 +1,3 @@
 bodega,ciudad
 Bodega Inti,Cusco
+Minimarket Sol,Trujillo

Una línea agregada y nada más. Así se ve una propuesta limpia ✨

4. Súbela a tu bifurcación

Manda la rama a origin, que es tu copia.

git push -q -u origin agrega-minimarkets
git ls-remote --heads origin
a9a0491c4de4c36c7b7cc8adea3385832f96b850	refs/heads/agrega-minimarkets
a9874ae5ade9ebff480ec9f29629b1b651573849	refs/heads/main

Dos ramas allá: la original y la tuya.

5. Trae lo nuevo del original

El proyecto avanzó mientras esperabas. Ponte al día.

cd ../catalogo
printf 'ciudad,monto\nLima,1200\n' > ciudades.csv
git add ciudades.csv
git commit -q -m "Entra el corte por ciudad"
git push -q ../catalogo-servidor.git main
cd ../trabajo
git fetch -q upstream
git switch -q main
git merge -q upstream/main
ls
bodegas.csv
ciudades.csv

El archivo nuevo del original ya está en tu main, y tu rama sigue intacta.

6. Actualiza tu propuesta

Lleva lo nuevo a tu rama para que la propuesta no envejezca.

git switch -q agrega-minimarkets
git merge -q main
ls
cat bodegas.csv
git log --oneline -3
bodegas.csv
ciudades.csv
bodega,ciudad
Bodega Inti,Cusco
Minimarket Sol,Trujillo
bc33316 Merge branch 'main' into agrega-minimarkets
a9a0491 Se agrega el minimarket de Trujillo
b648c87 Entra el corte por ciudad

El corte por ciudad y tu minimarket conviven. La propuesta sigue siendo tuya y está al día.

7. Intenta subir al proyecto original

Prueba a mandar tu rama a una dirección que no existe, que es lo que pasa cuando escribes mal el remoto.

git push otro-remoto agrega-minimarkets
fatal: 'otro-remoto' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Git no inventa destinos: si el apodo no está configurado, se planta 🛑

Lo que te llevas

Fork, clone, rama, push y un clic. Y una rama por propuesta, siempre.

¿Tienes alguna duda o consulta?