Manejo de Git para descargas y entregas
En esta página se explica el mecanismo de entrega para los labs y TPs de la materia. Los puntos clave son:
-
a cada estudiante y a cada grupo se les asigna un repositorio privado donde realizar el trabajo y subir el código;
-
una vez completado el trabajo, la entrega se realiza desde ese mismo repositorio mediante un pull request;
-
para cada lab o TP, hay un repositorio público donde se proporciona un esqueleto o código inicial sobre el que basar la implementación.
El método aquí descrito es el único mecanismo de entregas válido, y es obligatorio seguir todos los pasos para garantizar que la entrega sea aceptada.
Índice
Repositorio privado
Durante la cursada, se proporciona a cada estudiante un repositorio privado en la organización fiubatps de GitHub. Este repositorio suele tener la forma sisop_año_apellido, por ejemplo: github.com:fiubatps/sisop_2020a_mendez
.
Para los trabajos prácticos en grupo se proporciona un segundo repositorio privado siguiendo el esquema sisop_año_numgrupo_apellidos, por ejemplo: github.com:fiubatps/sisop_2020a_g8_mendez_simo
.
Descarga inicial
Cada estudiante deberá clonar sus repositorios privados en su computadora personal, bien vía http (con contraseña), o ssh (con clave privada):
1
2
3
4
5
# Por HTTP
$ git clone https://github.com/fiubatps/sisop_2020a_mendez
# Por SSH
$ git clone git@github.com:fiubatps/sisop_2020a_g8_mendez_simo
Se le puede agregar un segundo parámetro a git clone para usar un nombre de directorio más corto, por ejemplo “labs” o “tps”, respectivamente:
1
2
$ git clone git@github.com:fiubatps/sisop_2020a_simo labs
$ git clone git@github.com:fiubatps/sisop_2020a_g8_mendez_simo tps
Cada operación git clone resulta en un repositorio local que es copia del repositorio remoto alojado en GitHub. Para poder conectarse en futuras operaciones, Git se guarda la dirección del repositorio remoto bajo el alias origin. Pueden estar presentes otros repositorios remotos bajo otros alias.
Elección de rama local
En la materia se realizan dos tipos de trabajos distintos:
- los labs individuales, que son relativamente independientes entre sí
- los trabajos prácticos grupales, que suelen implementarse cada uno sobre el anterior
Así, para cada uno de los repositorios privados (individual y grupal) se trabaja de manera distinta en cuanto a ramas se refiere:
-
para los trabajos prácticos, la implementación se realiza directamente sobre la rama principal (normalmente llamada master). Esto quiere decir que tras realizar git clone, ya se está en la rama adecuada para integrar el esqueleto.
-
en cambio, para los labs no es deseable ver la solución de uno de ellos mezclada en el pull request de otro (pues son independientes); siendo así, la implementación de cada lab se realizará en una rama local distinta, que deberá ser creada con git checkout -b.
Las instrucciones exactas para crear las ramas se proporcionan más adelante, en la sección Integración del código.
Por otra parte, se recomienda subir de manera periódica el código a GitHub para que el repositorio remoto actúe como copia de seguridad del trabajo:
1
$ git push
Además, para realizar consultas sobre el código, se debe subir siempre la última versión al repositorio privado. De esta manera los docentes puedan consultarlo sin que sea necesario enviarlo por correo.
Autenticación sin contraseña
En la configuración estándar, Git pedirá una contraseña cada vez que se comunique con el repositorio remoto en GitHub (ya sea para push, pull, o clone). Hay dos maneras de evitar esto:
-
usar el protocolo ssh en combinación con la herramienta
ssh-agent
del sistema, tal y como se explica en la documentación oficial de GitHub, Connecting to GitHub with SSH (o, en castellano: Conectar a GitHub con SSH). -
utilizar el protocolo https y usar el “ayudante de credenciales” del sistema operativo para almacenar la contraseña: Caching your GitHub password in Git (o, en castellano: Guardar en caché tu contraseña de GitHub en Git).
Esqueleto del TP
Ubicación pública
Para cada lab y trabajo práctico se proporcionará un repositorio público con un esqueleto sobre el que obligatoriamente realizar la implementación. En cada enunciado, se proporcionará la siguiente información:
- la dirección del repositorio donde se aloja el esqueleto
- la rama exacta que contiene el esqueleto a usar para un lab o TP en particular
- si el esqueleto debe integrarse sobre un trabajo anterior ya completado, o si se parte de él desde cero
Como ejemplo ilustrativo, podría suceder que dos labs hipotéticos llamados athena y apollo alojasen su código inicial en repositorios distintos:
- lab athena: repositorio
github.com/fisop/athena
, rama master - lab apollo: repositorio
github.com/fisop/apollo
, rama master
pero que otros dos labs, themis y prometheus, tuvieran sus esqueletos en ramas distintas de un mismo repositorio:
- lab themis: repositorio
github.com/fisop/titans
, rama themis - lab prometheus: repositorio
github.com/fisop/titans
, rama prometheus
Agregar remote
El paso previo a la descarga del esqueleto es agregar su repositorio público como un “remote” cuyo alias haga referencia al lab o TP. Así, para agregar los repositorios de ejemplo descritos en la sección anterior, se debería hacer:
1
2
3
4
$ cd labs
$ git remote add esqueleto_athena https://github.com/fisop/athena
$ git remote add esqueleto_apollo https://github.com/fisop/apollo
$ git remote add esqueleto_titans https://github.com/fisop/titans
Nota al margen: los alias de estos remotes (esqueleto_athena, esqueleto_apollo, etc.) son arbitrarios; podría haberse usado cualquier otro nombre sea skel_athena, catedra_apollo o, meramente, algo bien breve como titans.
Integración del código
Para realmente tener el código inicial en el repositorio local, se debe descargar mediante git fetch, e integrar en la rama local adecuada para que aparezca en el directorio de trabajo. Los pasos siempre son:
- pararse en el repositorio privado (individual o grupal) usando cd
- realizar la integración del esqueleto en master. Para ello:
- bajarse los últimos cambios del esqueleto con git fetch
- pararse en la rama master con git checkout
- integrar el esqueleto allí con git merge
- crear una rama de referencia a esta integración con git branch
- (solamente para labs independientes) crear, a partir del esqueleto, una rama de trabajo separada con git checkout -b
- enviar las nuevas ramas al repositorio remoto con git push
Por ejemplo, si athena y apollo son labs que se implementan de manera independiente en las semanas 2 y 6, se haría:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(Semana 1: clone)
$ git clone git@github.com:fiubatps/sisop_2020a_simo labs
(Semana 2: Lab Athena, en su propia rama)
$ cd labs
$ git fetch -v esqueleto_athena
$ git checkout master
$ git merge --no-ff -m "Integrar esqueleto del lab athena" esqueleto_athena/master
$ git branch base_athena
$ git checkout -b lab_athena esqueleto_athena/master
$ git push -u origin --all
(Semana 6: Lab Apollo, en su propia rama)
$ cd labs
$ git fetch -v esqueleto_apollo
$ git checkout master
$ git merge --no-ff -m "Integrar esqueleto del lab apollo" esqueleto_apollo/master
$ git branch base_apollo
$ git checkout -b lab_apollo esqueleto_apollo/master
$ git push -u origin --all
Si, hipotéticamente, los labs themis y prometheus se implementaran uno
sobre el otro, el procedimiento sería el mismo excepto que se eliminaría el
paso git checkout -b
. Esto ocurre en los TPs de JOS:
1
2
3
4
5
6
7
8
9
(Semana 8: TP0 de JOS, en master)
$ cd tps
$ git fetch -v esqueleto_jos
$ git checkout master
$ git merge --no-ff -m "Integrar esqueleto del TP0" esqueleto_jos/tp0
$ git branch base_tp0
$ git push -u origin --all
Es obligatorio hacer git merge del esqueleto en el repositorio privado (no es suficiente meramente copiar los archivos). No se corregirán trabajos que no compartan el historial de Git con el repositorio público.
Directorio de trabajo
Una consecuencia de usar ramas indepedientes para los labs es que no es posible trabajar, en un mismo directorio, en más de un lab a la vez. Esto, en general, no constituye un problema, pues no se suele trabajar en más de un lab al mismo tiempo; pero puede resultar molesto en caso de sí necesitar realizar cambios en dos labs de manera concurrente.
La manera estándar de trabajar con ramas independientes sería usar git checkout para alternar entre ellas. Así, si se estuviera trabajando en el lab apollo y se desease realizar algún cambio en el lab anterior (athena), el procedimiento sería:
1
2
3
4
$ git checkout lab_athena
# realizar los cambios...
$ git commit
$ git checkout lab_apollo
Para que esto funcione, el directorio de trabajo debe estar previamente “limpio” (esto es, que git status no reporte cambios). Además, los archivos del lab apollo desaparecerían temporalmente del directorio de trabajo hasta que se volviese a la rama original, lo cual puede desorientar al editor o IDE.
Una alternativa es asignar un directorio distinto a cada lab, pero sin hacer git clone de nuevo. Git ofrece esta funcionalidad mediante el concepto de worktree. A través de ellos es posible tener varias “copias de trabajo” de un mismo repositorio, siempre que a cada copia se le asigne una rama distinta.
Para usar worktrees con las ramas de los labs, solamente sería necesario sustituir la orden git checkout -b explicada arriba por:
1
2
3
4
5
6
7
(Semana 2.)
...
$ git worktree add -b lab_athena ../athena esqueleto_athena/master
(Semana 6.)
...
$ git worktree add -b lab_apollo ../apollo esqueleto_apollo/master
donde ../athena
y ../apollo
representan las rutas donde se alojarán las copias de trabajo adicionales (una por cada lab).
Así, en caso de usar worktrees el directorio principal del repositorio quedaría siempre en la rama master y, siguiendo el ejemplo de arriba, se crearían sendos directorios adicionales al mismo nivel que el repositorio principal:
1
2
$ ls
athena apollo labs
Entrega vía pull request
Una vez terminado el lab o TP, se debe crear un pull request en Github, bien visitando de manera directa https://github.com/fiubatps/sisop_<año>_<apellido>/compare
; bien con la opción New pull request en la pestaña Pull requests del repositorio.1
Allí aparecerá una interfaz de creación de pull request en la que se deberá hacer tres cosas:
- elegir la rama base (a la izquierda)
- elegir la rama compare (a la derecha)
- una vez elegidas, hacer click en Create pull request y completar los siguientes campos: Título, Reviewers y Assignees.
Ramas base y compare
Tanto para labs como para TPs, la rama base es siempre la rama que fue creada en el momento de integración del esqueleto, concretamente en el paso: “crear una rama de referencia a esta integración con git branch”. Por ejemplo base_athena, base_themis o, llegado el caso, base_tp1.
En cambio, la rama compare varía entre labs y TPs:
-
para los labs, la rama compare es la rama creada con git checkout -b, por ejemplo lab_athena o lab_apollo.
-
para los TPs, la rama compare se crea a mano en el momento:
1
$ git push origin master:refs/heads/entrega_themis
O bien:
1
$ git push origin master:refs/heads/entrega_tp2
Así, en estos ejemplos la rama compare sería entrega_themis o entrega_tp2. No se debe usar master para este propósito.
Campos a completar
Antes de finalizar la creación del pull request, se deben completar los siguientes campos:
- título:
-
para entregas individuales, el nombre del lab más el apellido, siguiendo el formato:
1 2
[sisop] lab shell – Méndez [sisop] lab virt – Simó
-
para entregas grupales, se agrega el número de grupo a los apellidos, siguiendo el formato:
1 2
[sisop] jos tp3 – g8 (Méndez/Simó) [sisop] xv6 alloc – g9 (Fresia/Raik)
-
-
assignees: dado que los pull requests se crean desde una sola cuenta de GitHub, si el trabajo es grupal se debe incluir en este campo al resto de integrantes del grupo, a fin de que les lleguen las notificaciones sobre la corrección.
- reviewers: en caso de ya contar con un docente asignado para las correcciones, se le deberá incluir en este campo. En caso contrario, se deberá seleccionar fiubatps/sisop-adm.
Mecanismo de corrección
La corrección se realizará a través del pull request creado en el paso anterior. Así, el docente asignado revisará el código y realizará las correcciones y comentarios oportunos. Estos comentarios se recibirán por correo electrónico, y se podrán consultar también a través de las interfaces web de GitHub y (en su caso) Reviewable. Se recomienda la lectura de la corrección a través de las interfaces web, pues:
-
aparecerán los comentarios junto con el código a que estos se refieren (en otras palabras, los comentarios aparecerán con el contexto exacto en que se realizaron)
-
se podrá contestar a los comentarios de manera directa desde la interfaz web, lo cual permite saber con exactitud a qué comentario o corrección se refiere cada respuesta (cosa que no ocurre con igual facilidad por correo)
Junto con los comentarios, la corrección recibida indicará claramente:
- si el TP está aprobado o no;
- en caso de no estar aprobado, qué cambios es imprescindible realizar para poder aprobarlo;
- en caso de estar aprobado, si el corrector aceptaría cambios adicionales para mejorar la nota, y cuáles son estos cambios.
En caso de no estar claro qué es lo que se está pidiendo, se puede pedir una aclaración con el mecanismo de respuestas en el propio pull request, descrito arriba.
Reviewable
Algunos docentes utilizan Reviewable para revisar el código, en lugar de la interfaz de GitHub. En ese caso, se recomienda leer las correcciones en el sitio web de Reviewable, y no a través de GitHub (pues no aparecerían los comentarios con todo el contexto necesario). Para acceder a Reviewable, no es necesario crear una cuenta; es suficiente con usar la opción Sign in with GitHub.
Asimismo, los comentarios de Reviewable tienen un concepto de “prioridad” (o disposition, en inglés). En general, el significado en las correcciones de la materia es:
-
blocking (marcados con el ícono de prohibición ): si el TP no está aprobado, se debe corregir este ítem para poder aprobar; si está aprobado, para subir la nota se deben corregir TODOS los ítems marcados de esta manera.
-
discussing (marcados con el círculo vacío ): el ítem merece la pena ser corregido, pero no es obligatorio hacerlo.
-
informing (marcados con el ícono de información ): corrección menor o informativa.
Reentregas y mejoras
En caso de realizarse cambios (para aprobar o para subir nota), estos deben enviarse vía el mismo pull request que fue creado para la entrega, y no a a través de uno nuevo. Esto se consigue haciendo git push a la rama compare del pull request:
1
2
3
4
$ git checkout entrega_tp2
# ...
$ git commit ...
$ git push
O bien, si se usan worktrees:
1
2
3
4
$ cd shell
# ... realizar cambios
$ git commit ...
$ git push
Una vez enviados los cambios con git push, se deben hacer dos cosas:
-
Revisar la lista completa de comentarios realizados por el docente, y responder a los mismos indicando si se realizaron los cambios solicitados (en los casos más triviales es suficiente con responder Done o Hecho; Reviewable proporciona un botón para esto); si corresponde, responder también a cualquier pregunta que hubiera hecho el docente, e indicar qué decisiones se tomaron en la (re-)implementación.2
- En el caso de Reviewable, es importante que no queden “pending conversations”, esto es, que al enviar los comentarios, Reviewable no diga “waiting on … nombre del alumne”.
-
Una vez respondidos los comentarios, hacer explícito en el pull request que éste está listo para ser revisado de nuevo. Esto se puede hacer al tiempo que se envían los comentarios, incluyendo el acrónimo PTAL en la respuesta (estándar en la industria anglosajona con significado Please take another look).
Como alternativa, este paso también se puede realizar vía la interfaz de GitHub, con el ícono de solicitud de revisión (dos flechas en círculo ) que aparece al lado del campo Reviewer.
Como comentario final, es especialmente importante realizar las correcciones con gran atención al detalle, para que no suceda que una reentrega empeora la situación (esto es, que en una reentrega dejen de funcionar aspectos que sí funcionaban antes).
-
Para más información sobre pull requests, consultar la documentación de GitHub, About pull requests, o en castellano: Acerca de las solicitudes de extracción. ↩︎
-
Esta práctica es estándar en la industria, de manera que se le haga fácil a la persona que revisa la nueva versión saber qué se hizo y qué no, esto es, con qué se va a encontrar. ↩︎