Una vez que tienes la cuenta configurada, veremos algunos detalles útiles para ayudarte a participar en proyectos existentes.
Si quieres participar en un proyecto existente, en el que no tengas permisos de escritura, puedes bifurcarlo (hacer un ``fork''). Esto consiste en crear una copia completa del repositorio totalmente bajo tu control: se almacenará en tu cuenta y podrás escribir en él sin limitaciones.
Note
|
Históricamente, el término |
De esta forma, los proyectos no necesitan añadir colaboradores con acceso de escritura (push). La gente puede bifurcar un proyecto, enviar sus propios cambios a su copia y luego remitir esos cambios al repositorio original para su aprobación; creando lo que se llama un Pull Request, que veremos más adelante. Esto permite abrir una discusión para la revisión del código, donde propietario y participante pueden comunicarse acerca de los cambios y, en última instancia, el propietario original puede aceptarlos e integrarlos en el proyecto original cuando lo considere adecuado.
Para bifurcar un proyecto, visita la página del mismo y pulsa sobre el botón ``Fork'' del lado superior derecho de la página.
En unos segundos te redireccionarán a una página nueva de proyecto, en tu cuenta y con tu propia copia del código fuente.
GitHub está diseñado alrededor de un flujo de trabajo de colaboración específico, centrado en las solicitudes de integración (``pull request''). Este flujo es válido tanto si colaboras con un pequeño equipo en un repositorio compartido, como si lo haces en una gran red de participantes con docenas de bifurcaciones particulares. Se centra en el workflow ch03-git-branching.asc cubierto en ch03-git-branching.asc.
El funcionamiento habitual es el siguiente:
-
Se crea una rama a partir de
master
. -
Se realizan algunos commits hacia esa rama.
-
Se envía esa rama hacia tu copia (fork) del proyecto.
-
Abres un Pull Request en GitHub.
-
Se participa en la discusión asociada y, opcionalmente, se realizan nuevos commits.
-
El propietario del proyecto original cierra el Pull Request, bien fusionando la rama con tus cambios o bien rechazándolos.
Este es, básicamente, el flujo de trabajo del Responsable de Integración visto en ch05-distributed-git.asc, pero en lugar de usar el correo para comunicarnos y revisar los cambios, lo que se hace es usar las herramientas web de GitHub.
Veamos un ejemplo de cómo proponer un cambio en un proyecto de código abierto hospedado en GitHub, utilizando esta forma de trabajar.
Tony está buscando código para ejecutar en su microcontrolador Arduino, y ha encontrado un programa interesante en GitHub, en la dirección https://github.com/schacon/blink.
El único problema es que la velocidad de parpadeo es muy rápida, y piensa que es mucho mejor esperar 3 segundos en lugar de 1 entre cada cambio de estado. Luego, nuestra mejora consistirá en cambiar la velocidad y enviar el cambio al proyecto como un cambio propuesto.
Lo primero que se hace, es pulsar en el botón 'Fork' ya conocido para hacer
nuestra propia copia del proyecto. Nuestro nombre de usuario es `tonychacon''
por lo que la copia del proyecto tendrá como dirección
`https://github.com/tonychacon/blink
, y en esta copia es donde podemos
trabajar. La clonaremos localmente, crearemos una rama, realizaremos el cambio
sobre el código fuente y finalmente enviaremos esos cambios a GitHub.
$ git clone https://github.com/tonychacon/blink (1)
Cloning into 'blink'...
$ cd blink
$ git checkout -b slow-blink (2)
Switched to a new branch 'slow-blink'
$ sed -i '' 's/1000/3000/' blink.ino (3)
$ git diff --word-diff (4)
diff --git a/blink.ino b/blink.ino
index 15b9911..a6cc5a5 100644
--- a/blink.ino
+++ b/blink.ino
@@ -18,7 +18,7 @@ void setup() {
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
[-delay(1000);-]{+delay(3000);+} // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
[-delay(1000);-]{+delay(3000);+} // wait for a second
}
$ git commit -a -m 'three seconds is better' (5)
[slow-blink 5ca509d] three seconds is better
1 file changed, 2 insertions(+), 2 deletions(-)
$ git push origin slow-blink (6)
Username for 'https://github.com': tonychacon
Password for 'https://[email protected]':
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 340 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://github.com/tonychacon/blink
* [new branch] slow-blink -> slow-blink
-
Clonar nuestro fork en nuestro equipo
-
Crear la rama, que sea descriptiva
-
Realizar nuestros cambios
-
Comprobar los cambios
-
Realizar un commit de los cambios en la rama
-
Enviar nuestra nueva rama de vuelta a nuestro fork
Ahora, si miramos nuestra bifurcación en GitHub, veremos que aparece un aviso de creación de la rama y nos dará la oportunidad de hacer una solicitud de integración con el proyecto original.
También puedes ir a la página `Branches'' en
`https://github.com/<user>/<project>/branches
para localizar la rama
y abrir el Pull Request desde ahí.
Si pulsamos en el botón verde, veremos una pantalla que permite crear un título y una descripción para darle al propietario original una buena razón para tenerla en cuenta. Normalmente debemos realizar cierto esfuerzo en hacer una buena descripción para que el autor sepa realmente qué estamos aportando y lo valore adecuadamente.
También veremos la lista de commits de la rama que están por delante'' de la
rama
diff unificado'' de los cambios que
se aplicarían si se fusionasen con el proyecto original.master
(en este caso, la única) y un
Cuando seleccionas el botón 'Create pull request', el propietario del proyecto que has bifurcado recibirá una notificación de que alguien sugiere un cambio junto a un enlace donde está toda la información.
Note
|
Aunque los Pull Request se utilizan en proyectos públicos como este, donde el ayudante tiene un conjunto de cambios completos para enviar, también se utiliza en proyectos internos al principio del ciclo de desarrollo: puedes crear el Pull Request con una rama propia y seguir enviando commits a dicha rama después de crear el Pull Request, siguiendo un modelo iterativo de desarrollo, en lugar de crear la rama cuando ya has finalizado todo el trabajo. |
En este punto, el propietario puede revisar el cambio sugerido e incorporarlo (merge) al proyecto, o bien rechazarlo o comentarlo. Por ejemplo, si le gusta la idea pero prefiere esperar un poco.
La discusión, en los workflow de ch05-distributed-git.asc, tiene lugar por
correo electrónico, mientras que en GitHub tiene lugar en línea. El propietario
del proyecto puede revisar el diff'' y dejar un comentario pulsando en
cualquier línea del
diff''.
Cuando el responsable hace el comentario, la persona que solicitó la integración (y otras personas que hayan configurado sus cuentas para escuchar los cambios del repositorio) recibirán una notificación. Más tarde veremos cómo personalizar esto, pero si las notificaciones están activas, Tony recibiría un correo como este:
Cualquiera puede añadir sus propios comentarios. En Página de discusión del Pull Request vemos un ejemplo de propietario de proyecto comentando tanto una línea del código como dejando un comentario general en la sección de discusión. Puedes comprobar que los comentarios del código se insertan igualmente en la conversación.
El participante puede ver ahora qué tiene que hacer para que sea aceptado su cambio. Con suerte será poco trabajo. Mientras que con el correo electrónico tendrías que revisar los cambios y reenviarlos a la lista de correo, en GitHub puedes, simplemente, enviar un nuevo commit a la rama y subirla (push).
Si el participante hace esto, el coordinador del proyecto será notificado nuevamente y, cuando visiten la página, verán lo que ha cambiado. De hecho, al ver que un cambio en una línea de código tenía ya un comentario, GitHub se da cuenta y oculta el ``diff'' obsoleto.
Es interesante notar que si pulsas en Files Changed'' dentro del Pull
Request, verás el
diff unificado'', es decir, los cambios que se
introducirían en la rama principal si la otra rama fuera fusionada. En
términos de Git, lo que hace es mostrarte la salida del comando
git diff master … <rama>
. Mira en ch05-distributed-git.asc para saber
más sobre este tipo de ``diff''.
Otra cosa interesante es que GitHub también comprueba si el Pull Request se fusionaría limpiamente (de forma automática) dando entonces un botón para hacerlo. Este botón solo lo veremos si además somos los propietarios del repositorio. Si pulsas este botón, GitHub fusionará sin avance rápido, es decir, que incluso si la fusión pudiera ser de tipo avance-rápido, de todas formas crearía un commit de fusión.
Si quieres, puedes obtener la rama en tu equipo y hacer la fusión localmente.
Si fusionas esta rama en la rama master
y la subes a GitHub, el Pull
Request se cerrará de forma automática.
Este es el flujo de trabajo básico que casi todos los proyectos de GitHub utilizan. Se crean las ramas de trabajo, se crean con ellas los Pull Requests, se genera una discusión, se añade probablemente más trabajo a la rama y finalmente la petición es cerrada (rechazada) o fusionada.
Note
|
No solo forks
Observa que también puedes abrir un Pull Request entre dos ramas del mismo
repositorio. Si estás trabajando en una característica con alguien y ambos
tenéis acceso de escritura al repositorio, puedes subir una rama al mismo
y abrir un Pull Request de fusión con |
Ahora que sabemos cómo participar de forma básica en un proyecto de GitHub, veamos algunos trucos más acerca de los Pull Requests que ayudarán a usarlos de forma más eficaz.
Hay que entender que muchos proyectos no tienen la idea de que los Pull Requests sean colas de parches perfectos que se pueden aplicar limpiamente en orden, como sucede con los proyectos basados en listas de correo. Casi todos los proyectos de GitHub consideran las ramas de Pull Requests como conversaciones evolutivas acerca de un cambio propuesto, culminando en un ``diff'' unificado que se aplica fusionando.
Esto es importante, ya que normalmente el cambio se sugiere bastante antes de que el código sea suficientemente bueno, lo que lo aleja bastante del modelo basado en parches por lista de correo. Esto facilita una discusión más temprana con los colaboradores, lo que hace que la llegada de la solución correcta sea un esfuerzo de comunidad. Cuando el cambio llega con un Pull Request y los colaboradores o la comunidad sugieren un cambio, normalmente los parches no son directamente alterados, sino que se realiza un nuevo commit en la rama para enviar la diferencia que materializa esas sugerencias, haciendo avanzar la conversación con el contexto del trabajo previo intacto.
Por ejemplo, si miras de nuevo en Pull Request final, verás que el colaborador no reorganiza su commit y envía un nuevo Pull Request. En su lugar, lo que hace es añadir nuevos commits y los envía a la misma rama. De este modo, si vuelves a mirar el Pull Request en el futuro, puedes encontrar fácilmente todo el contexto con todas las decisiones tomadas. Al pulsar el botón ``Merge'', se crea un commit de fusión que referencia al Pull Request, con lo que es fácil localizar para revisar la conversación original, si es necesario.
Si el Pull Request se queda anticuado, o por cualquier otra razón no puede fusionarse limpiamente, lo normal es corregirlo para que el responsable pueda fusionarlo fácilmente. GitHub comprobará esto y te dirá si cada Pull Request tiene una fusión trivial posible o no.
Si ves algo parecido a Pull Request que no puede fusionarse limpiamente, seguramente prefieras corregir la rama de forma que se vuelva verde de nuevo y el responsable no tenga trabajo extra con ella.
Tienes dos opciones para hacer esto. Puedes, por un lado, reorganizar (rebase)
la rama con el contenido de la rama master
(normalmente esta es la rama desde
donde se hizo la bifurcación), o bien puedes fusionar la rama objetivo en
la tuya.
Muchos desarrolladores eligen la segunda opción, por las mismas razones que dijimos en la sección anterior. Lo que importa aquí es la historia y la fusión final, por lo que reorganizar no es mucho más que tener una historia más limpia y, sin embargo, es por lejos más complicado de hacer y con mayores posibilidades de error.
Si quieres fusionar en la rama objetivo para hacer que tu Pull Request sea fusionable, deberías añadir el repositorio original como un nuevo remoto, bajártelo (fetch), fusionar la rama principal en la tuya, corregir los problemas que surjan y finalmente enviarla (push) a la misma rama donde hiciste la solicitud de integración.
Por ejemplo, supongamos que en el ejemplo ``tonychacon'' que hemos venido usando, el autor original hace un cambio que crea un conflicto con el Pull Request. Seguiremos entonces los siguientes pasos:
$ git remote add upstream https://github.com/schacon/blink (1)
$ git fetch upstream (2)
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
Unpacking objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
From https://github.com/schacon/blink
* [new branch] master -> upstream/master
$ git merge upstream/master (3)
Auto-merging blink.ino
CONFLICT (content): Merge conflict in blink.ino
Automatic merge failed; fix conflicts and then commit the result.
$ vim blink.ino (4)
$ git add blink.ino
$ git commit
[slow-blink 3c8d735] Merge remote-tracking branch 'upstream/master' \
into slower-blink
$ git push origin slow-blink (5)
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 682 bytes | 0 bytes/s, done.
Total 6 (delta 2), reused 0 (delta 0)
To https://github.com/tonychacon/blink
ef4725c..3c8d735 slower-blink -> slow-blink
-
Añadir el repositorio original como un remoto llamado ``upstream''
-
Obtener del remoto lo último enviado al repositorio
-
Fusionar la rama principal en la nuestra
-
Corregir el conflicto surgido
-
Enviar de nuevo los cambios a la rama del Pull Request
Cuando haces esto, el Pull Request se actualiza automáticamente y se re-chequea para ver si es posible un fusionado automático o no.
Una de las cosas interesantes de Git es que puedes hacer esto continuamente.
Si tienes un proyecto con mucha historia, puedes fácilmente fusionarte la
rama objetivo (master
) cada vez que sea necesario, evitando
conflictos y haciendo que el proceso de integración de tus cambios sea muy
manejable.
Si finalmente prefieres reorganizar la rama para limpiarla, también puedes hacerlo, pero se recomienda no forzar el push sobre la rama del Pull Request. Si otras personas se la han bajado y hacen más trabajo en ella, provocarás los problemas vistos en ch03-git-branching.asc. En su lugar, envía la rama reorganizada a una nueva rama de GitHub y abre con ella un nuevo Pull Request, con referencia al antiguo, cerrando además éste último.
La siguiente pregunta puede ser ``¿cómo hago una referencia a un Pull Request antiguo?''. La respuesta es, de varias formas.
Comencemos con cómo referenciar otro Pull Request o una incidencia (Issue).
Todas las incidencias y Pull Requests tienen un número único que los
identifica. Este número no se repite dentro de un mismo proyecto. Por ejemplo,
dentro de un proyecto solo podemos tener un Pull Request con el número 3, y
una incidencia con el número 3. Si quieres hacer referencia al mismo, basta
con poner el símbolo #
delante del número, en cualquier comentario o
descripción del Pull Request o incidencia. También se puede poner referencia
tipo usuario#numero
para referirnos a un Pull Request o incidencia en
una bifurcación que haya creado ese usuario, o incluso puede usarse la forma
usuario/repo#num
para referirse a una incidencia o Pull Request en otro
repositorio diferente.
Veamos un ejemplo. Supongamos que hemos reorganizado la rama del ejemplo anterior, creado un nuevo Pull Request para ella y ahora queremos hacer una referencia al viejo Pull Request desde el nuevo. También queremos hacer referencia a una incidencia en la bifurcación del repositorio, y una incidencia de un proyecto totalmente distinto. Podemos rellenar la descripción justo como vemos en Referencias cruzadas en un Pull Request..
Cuando enviamos este Pull Pequest, veremos todo como en Cómo se ven las referencias cruzadas en el Pull Request..
Observa que la URL completa de GitHub que hemos puesto ahí ha sido acortada a la información que necesitamos realmente.
Ahora, si Tony regresa y cierra el Pull Request original, veremos que GitHub crea un evento en la línea de tiempo del Pull Request. Esto significa que cualquiera que visite este Pull Request y vea que está cerrado, puede fácilmente enlazarlo al que lo hizo obsoleto. El enlace se mostrará tal como en Cómo se ven las referencias cruzadas en el Pull Request..
Además de los números de incidencia, también puedes hacer referencia a un
commit'' específico usando la firma SHA-1. Puedes utilizar la cadena SHA-1
completa (de 40 caracteres) y al detectarla GitHub en un comentario, la
convertirá automáticamente en un enlace directo al
commit''. Nuevamente,
puedes hacer referencia a commits en bifurcaciones o en otros
repositorios del mismo modo que hicimos con las incidencias.
El enlazado a otras incidencias es sólo el comienzo de las cosas interesantes que se pueden hacer con cualquier cuadro de texto de GitHub. En las descripciones de las incidencias y los Pull Requests, así como en los comentarios y otros cuadros de texto, se puede usar lo que se conoce como ``formato Markdown de GitHub''. El formato Markdown es como escribir en texto plano pero que luego se convierte en texto con formato.
Mira en Ejemplo de texto en Markdown y cómo queda después. un ejemplo de cómo los comentarios o el texto puede escribirse y luego formatearse con Markdown.
En GitHub se añaden algunas cosas a la sintaxis básica del Markdown. Son útiles al tener relación con los Pull Requests o las incidencias.
La primera característica añadida, especialmente interesante para los Pull Requests, son las listas de tareas. Una lista de tareas es una lista de cosas con su marcador para indicar que han terminado. En un Pull Requests o una incidencia nos sirven para anotar la lista de cosas pendientes a realizar para considerar terminado el trabajo relacionado con esa incidencia.
Puedes crear una lista de tareas así:
- [X] Write the code
- [ ] Write all the tests
- [ ] Document the code
Si incluimos esto en la descripción de nuestra incidencia o Pull Request, lo veremos con el aspecto de Cómo se ven las listas de tareas de Markdown.
Esto se suele usar en Pull Requests para indicar qué cosas hay que hacer en la rama antes de considerar que el Pull Request está listo para fusionarse. La parte realmente interesante, es que puedes pulsar los marcadores para actualizar el comentario indicando qué tareas se finalizaron, sin necesidad de editar el texto markdown del mismo.
Además, GitHub mostrará esas listas de tareas como metadatos de las páginas que las muestran. Por ejemplo, si tienes un Pull Request con tareas y miras la página de resumen de todos los Pull Request, podrás ver cuánto trabajo queda pendiente. Esto ayuda a la gente a dividir los Pull Requests en subtareas y ayuda a otras personas a seguir la evolución de la rama. Se puede ver un ejemplo de esto en Resumen de lista de tareas en la lista de PR..
Esto es increíblemente útil cuando se abre un Pull Request al principio y se quiere usar para seguir el progreso de desarrollo de la característica.
También se pueden añadir fragmentos de código a los comentarios. Esto resulta útil para mostrar algo que te gustaría probar antes de ponerlo en un commit de tu rama. Esto también se suele usar para añadir ejemplos de código que no funciona u otros asuntos.
Para añadir un fragmento de código, lo tienes que encerrar entre los símbolos del siguiente ejemplo.
```java
for(int i=0 ; i < 5 ; i++)
{
System.out.println("i is : " + i);
}
```
Si añades junto a los símbolos el nombre de un lenguaje de programación, como hacemos aquí con 'java', GitHub intentará hacer el resaltado de la sintaxis del lenguaje en el fragmento. En el caso anterior, quedaría con el aspecto de Cómo se ve el fragmento de código..
Si estás respondiendo a un comentario grande, pero solo a una pequeña parte,
puedes seleccionar la parte que te interesa y citarlo, para lo que precedes
cada línea citada del símbolo >
. Esto es tan útil que hay un atajo de teclado
para hacerlo: si seleccionas el texto al que quieres contestar y pulsas la
tecla r
, creará una cita con ese texto en la caja del comentario.
Un ejemplo de cita:
> Whether 'tis Nobler in the mind to suffer
> The Slings and Arrows of outrageous Fortune,
How big are these slings and in particular, these arrows?
Una vez introducido, el comentario se vería como en Rendered quoting example..
Finalmente, también puedes usar emojis (emoticonos) en tus comentarios. Se
utiliza mucho en las discusiones de las incidencias y Pull Requests de GitHub.
Incluso tenemos un asistente de emoji: si escribes un comentario y tecleas el
caracter :
, verás cómo aparecen iconos para ayudarte a completar el
que quieras poner.
Los emoticonos son de la forma :nombre:
en cualquier punto del comentario.
Por ejemplo, podráis escribir algo como esto:
I :eyes: that :bug: and I :cold_sweat:.
:trophy: for :microscope: it.
:+1: and :sparkles: on this :ship:, it's :fire::poop:!
:clap::tada::panda_face:
Al introducir el comentario, se mostraría como Comentando con muchos emoji..
No es que sean especialmente útiles, pero añaden un elemento de gracia y emoción a un medio en el que de otro modo sería mucho más complicado transmitir las emociones.
Note
|
Actualmente hay bastantes sitios web que usan los emoticonos. Hay una referencia interesante para encontrar el emoji que necesitas en cada momento: |
Esto no es técnicamente parte de las mejoras a Markdown de GitHub, pero es increíblemente útil. En adición a añadir enlaces con imágenes en el formato Markdown a los comentarios, GitHub permite arrastrar y soltar imágenes en las áreas de texto para insertarlas.
Si vuelves a Referencias cruzadas en un Pull Request., verás una pequeña nota sobre el área de texto ``Parsed as Markdown''. Si pulsas ahí te dará una lista completa de cosas que puedes hacer con el formato Markdown de GitHub.