Trabajando con Git y GitHub

Esta sección explica cómo la comunidad puede contribuir código a Django mediante solicitudes de fusión. Si está interesado en saber cómo mergers manejan ellas, consulte Comitir código.

A continuación, vamos a mostrar cómo crear una solicitud de fusión de GitHub que contenga los cambios para el ticket Trac #xxxxx. Al crear una solicitud de fusión completamente lista, hará más fácil el trabajo del revisor, lo que significa que su trabajo es más probable que se fusiona en Django.

También podría subir un parche tradicional a Trac, pero es menos práctico para las revisiones.

Instalando Git

Django utiliza Git para su control de versiones. Puedes descargar Git, pero a menudo es más fácil instalarlo con el administrador de paquetes de tu sistema operativo.

El repositorio de código fuente de Django se hospeda en GitHub. Se recomienda que también trabajes utilizando GitHub.

Después de instalar Git, la primera cosa que debes hacer es configurar tu nombre y correo electrónico:

$ git config --global user.name "Your Real Name"
$ git config --global user.email "you@email.com"

Ten en cuenta que user.name debe ser tu nombre real, no tu nick de GitHub. GitHub debería conocer el correo electrónico que utilices en el campo user.email, ya que se utilizará para asociar tus commits con tu cuenta de GitHub.

Configurando un repositorio local

Cuando hayas creado tu cuenta de GitHub, con el nick «GitHub_nick», y forked el repositorio de Django, crea una copia local de tu fork:

git clone https://github.com/GitHub_nick/django.git

Esto creará un nuevo directorio llamado «django», que contendrá una copia clonada de tu repositorio de GitHub. El resto de comandos Git en esta página deben ejecutarse dentro del directorio clonado, así que cambia a él ahora:

cd django

Tu repositorio de GitHub se llamará «origin» en Git.

También debes configurar django/django como un remoto «upstream» (es decir, indica a Git que el repositorio de referencia Django fue la fuente de tu fork de él):

git remote add upstream https://github.com/django/django.git
git fetch upstream

Puedes agregar otros remotos de manera similar, por ejemplo:

git remote add akaariai https://github.com/akaariai/django.git

Trabajando en un ticket

Cuando estés trabajando en un ticket, crea una nueva rama para el trabajo y basa ese trabajo en upstream/main.

git checkout -b ticket_xxxxx upstream/main

La bandera -b crea una nueva rama para ti localmente. No dudes en crear nuevas ramas, incluso para las cosas más pequeñas - eso es lo que están ahí para ello.

Si en cambio estabas trabajando para una corrección en la rama 1.4, harías lo siguiente:

git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x

Asume que el trabajo se está llevando a cabo en la rama ticket_xxxxx. Haz algunos cambios y haz un seguimiento de ellos:

git commit

Cuando estás escribiendo el mensaje de commit, sigue las directrices del mensaje de commit (directrices-del-mensaje-de-commit) para facilitar el trabajo al integrador. Si te sientes incómodo con el inglés, trata al menos de describir con precisión qué hace el commit.

Si necesitas realizar trabajo adicional en tu rama, haz commits tan a menudo como sea necesario:

git commit -m 'Added two more tests for edge cases'

Publicación de trabajo

Puedes publicar tu trabajo en GitHub ejecutando:

git push origin ticket_xxxxx

When you go to your GitHub page, you will notice a new rama ha sido creada.

Si estás trabajando en un ticket de Trac, debes mencionar en el ticket que tu trabajo está disponible desde la rama ticket_xxxxx de tu repositorio de GitHub. Incluye un enlace a tu rama.

Ten en cuenta que la rama anterior se llama «rama de tema» en el parlamento Git. Estás libre para reescribir la historia de esta rama, utilizando git rebase por ejemplo. Las demás personas no deberían basar su trabajo en tal rama, porque su clonación se volvería corrupta cuando editas los commits.

También hay «ramas públicas». Estas son ramas de las que otras personas están supuestas a forkear, por lo que la historia de estas ramas nunca debería cambiar. Ejemplos buenos de ramas públicas son las main y stable/A.B.x ramas en el repositorio django/django.

Cuando creas que tu trabajo está listo para ser incorporado a Django, debes crear una solicitud de extracción en GitHub. Una buena solicitud de extracción significa:

  • commits con un cambio lógico en cada uno, siguiendo el estilo de codificación,

  • mensajes bien formados para cada commit: una línea de resumen y luego párrafos envueltos a 72 caracteres – véase las directrices de commiteo para más detalles,

  • documentación y pruebas, si es necesario – en realidad, siempre se necesitan pruebas, excepto para cambios de documentación.

La suite de pruebas debe pasar y la documentación debe construirse sin advertencias.

Una vez que hayas creado tu solicitud de extracción, debes agregar un comentario en el ticket relacionado explicando lo que has hecho. En particular, debes mencionar el entorno en el que ejecutaste las pruebas, por ejemplo: «todos los tests pasan bajo SQLite y MySQL».

Los pull requests en GitHub tienen solo dos estados: abierto y cerrado. El integrador que se encargará de tu pull request tiene solo dos opciones: fusionarlo o cerrarlo. Por esta razón, no es útil hacer un pull request hasta que el código esté listo para la fusión – o lo suficientemente cerca que un integrador termine él mismo.

Rebasing de ramas

En el ejemplo anterior, creaste dos commits: el commit «Solucionado ticket_xxxxx» y el commit «Agregados dos pruebas más».

No queremos tener toda la historia de tu proceso de trabajo en tu repositorio. Tu commit «Agregados dos pruebas más» sería ruido inútil. En su lugar, preferimos tener solo un commit que contenga todo tu trabajo.

Para reescribir la historia de tu rama puedes combinar los commits en uno utilizando el rebasing interactivo:

git rebase -i HEAD~2

La expresión HEAD~2 anterior es una abreviatura para los dos últimos commits. El comando anterior abrirá un editor mostrando los dos commits, con la palabra «pick» como prefijo.

Cambia «pick» en la segunda línea a «squash» en su lugar. De esta manera se conservará el primer commit y se combinarán los segundos commits en el primero. Guarda y cierra el editor. Se debería abrir una ventana de edición adicional, para que puedas reescribir el mensaje del commit ahora que incluye ambos pasos.

También puedes utilizar la opción «edit» en el rebasing. De esta manera puedes cambiar un solo commit, por ejemplo para corregir un error tipográfico en una docstring:

git rebase -i HEAD~3
# Choose edit, pick, pick for the commits
# Now you are able to rework the commit (use git add normally to add changes)
# When finished, commit work with "--amend" and continue
git commit --amend
# Reword the commit message if needed
git rebase --continue
# The second and third commits should be applied.

Si tu rama de tema ya está publicada en GitHub, por ejemplo si estás haciendo cambios menores para tener en cuenta una revisión, necesitarás forzar el empuje de los cambios:

git push -f origin ticket_xxxxx

Ten en cuenta que esto reescribirá la historia del ticket_xxxxx - si comprobases las hashes de commit antes y después de la operación en GitHub notarías que no coinciden. Esto es aceptable, ya que la rama es una rama de tema, y nadie debería estar basando su trabajo en ella.

Después que upstream ha cambiado

Cuando upstream (django/django) ha cambiado, debes rebasar tu trabajo. Para hacer esto, utiliza:

git fetch upstream
git rebase upstream/main

El trabajo se rebase automáticamente utilizando la rama en la que te has forked, en el caso de ejemplo utilizando upstream/main.

La orden rebase elimina temporalmente todos los commits locales, aplica los commits de upstream y luego vuelve a aplicar tus commits locales en el trabajo.

Si hay conflictos de fusión, necesitarás resolverlos y luego utilizar git rebase --continue. En cualquier momento puedes utilizar git rebase --abort para regresar al estado original.

Ten en cuenta que deseas rebasar sobre upstream, no fusiónar la de upstream.

La razón por la cual es que rebasando, tus commits siempre estarán encima de el trabajo de upstream, no mezclados con los cambios en upstream. De esta manera tu rama contendrá solo commits relacionados con su tema, lo que facilita la compactación.

Después de revisión

Es poco común obtener cualquier cantidad significativa de código en el núcleo sin cambios solicitados por los revisores. En este caso, a menudo es una buena idea agregar los cambios como un commit incremental único a tu trabajo. Esto permite al revisor verificar fácilmente qué cambios has realizado.

En este caso, haz los cambios requeridos por el revisor. Comitea con la frecuencia necesaria. Antes de publicar los cambios, rebasa tu trabajo. Si agregaste dos commits, ejecutarías:

git rebase -i HEAD~2

Squash el segundo commit en el primero. Escribe un mensaje de commit del tipo:

Made changes asked in review by <reviewer>

- Fixed whitespace errors in foobar
- Reworded the docstring of bar()

Finalmente, envía tu trabajo nuevamente a tu repositorio de GitHub. Dado que no tocó los commits públicos durante la rebase, no deberías necesitar enviar con fuerza:

git push origin ticket_xxxxx

Tu solicitud de extracción debe contener ahora el nuevo commit también.

Ten en cuenta que la fusión es probable que aplaste el commit de revisión en el commit anterior al cometer el código.

Trabajando en una parche

Una de las formas en que los desarrolladores pueden contribuir a Django es revisando parches. Esos parches existirán típicamente como solicitudes de extracción en GitHub y se pueden integrar fácilmente en tu repositorio local:

git checkout -b pull_xxxxx upstream/main
curl -L https://github.com/django/django/pull/xxxxx.patch | git am

Esto creará una nueva rama y luego aplicará las modificaciones de la solicitud de extracción a ella. En este punto puedes ejecutar los tests o hacer cualquier otra cosa que necesites para investigar la calidad del parche.

Para más detalles sobre el trabajo con solicitudes de extracción, consulta las directrices para fusiones.

Resumen

  • Trabaja en GitHub si puedes.

  • Anuncia tu trabajo en el ticket de Trac vinculando a tu rama de GitHub.

  • Cuando tengas algo listo, haz una solicitud de extracción.

  • Haz tus solicitudes de extracción lo mejor posible.

  • Al hacer correcciones a tu trabajo, utiliza git rebase -i para compactar los commits.

  • Cuando el código upstream haya cambiado, haz git fetch upstream; git rebase.