Lo que he aprendido: registro de cambios en un documento LaTeX con git

Estoy echando una mano a mi hermano con una documentación to guapa para un tema que mejor os cuenta él y me preguntó cómo incluir un registro de cambios en el documento. Un registro de cambios no puede ser muy complejo de hacer si estamos usando git, pensé, así que me puse a investigar las diferentes alternativas, empezando por la opción evidente: git log.

Jugando con git log

Empecemos por los inicios, como todos los que usáis git sabéis mejor que yo, git log nos permite dar un formato al historial de commits con las opciones --pretty y --format. Por ejemplo, podemos mostrar la fecha y la descripción del commit haciendo:

git log --pretty=format:"%ad%x09%s" --date=short > cambios.log

Donde %ad hace referencia a la fecha, %x09 indica que separe este campo del siguiente con un tabulador y %s el mensaje del commit. La opción --date=short sirve para que escriba una fecha compacta sin el día de la semana y la hora. En este caso redireccionamos la salida al fichero cambio.log.

Para que nos hagamos una idea, si ejecutamos la orden anterior en el repo del curso de LaTeX, el fichero cambios.log tendrá esta pinta:

2017-04-18  Publicar cap11
2017-04-15  Actualizar borrador cap11 y ejemplos
2017-04-14  Actualizar borrador de cap 11 y ejemplos de código
2017-04-13  Actualizar borrador y ejemplos de cap11
2017-04-12  Actualizar cap 11. Añadir ejemplos
2017-04-10  Pasar cap 9 y 10 a tex. Actualizar borrador de 11
2017-04-07  Capítulo 10 final

Podemos ir más allá y darle formato LaTeX a nuestro registro de cambios cambiando la expresión para formatear la salida y redireccionando a un archivo tex. A mí se me ha ocurrido ser separar los campos como si estuviesen en una tabla:

git log --date=short --pretty=format:'%ad & %s \\' > log.tex

De esta manera puedo definir la tabla en mi documento e incluir el registro de cambios con el comando \input:

\begin{tabular}{l l}
\textbf{Fecha} & \textbf{Descripción} \\
 & \\
\input{log.tex}
\end{tabular}

Esto me crea una simpática tabla de cambios donde le pida.

Filtrar por etiquetas

El problema que tiene esta versión es que si somos muy commiteadores (como servidora) puede ser una lista infumable. Una posible solución es etiquetar en puntos clave nuestro repo:

git tag v1

Y luego filtrar para que solo nos muestre los commits con etiqueta con:

git log --no-walk --tags --date=short --pretty=format:'%ad & %s \\' > log.tex

Si queremos que aparezca el nombre de la etiqueta, en lugar de git log necesitamos un for-each-ref, que tiene una sintaxis ligeramente diferente. Este comando busca por las referencias y nos saca la información con el formato que le pidamos. Para que nos escriba la etiqueta, la fecha y el mensaje necesitaríamos algo en esta línea:

git for-each-ref --format="%(refname:short) & %(authordate:short) & %(subject) \\\\" refs/tags > log.tex

En este caso hay cuatro barras porque hay que escaparlas y por lo tanto con dos barras se pinta una. Como sacamos tres datos tenemos que modificar la tabla, lo que no tiene mayor problema:

\begin{tabular}{l l l}
\textbf{Versión} & \textbf{Fecha} & \textbf{Descripción} \\
& & \\
\input{log.tex} % incluir datos
\end{tabular}

Esto ya está más cerca de ser una solución práctica, solo nos queda automatizarla.


NOTA: Gracias a los comentarios he descubierto que dependiendo de si usamos etiquetas lightweight (git tag v1) o annotated (git tag -a v1 -m "Primera versión") el modo de mostrar la fecha es diferente:

  • Para el caso lightweight como la etiqueta referencia a un commit funciona %(authordate). Esto es lo que yo he hecho.
  • Para el caso annotated hay que usar o bien %(*authordate) o %(taggerdate). El mensaje %(subject) muestra en este caso el mensaje del tag. Entiendo que en este segundo caso el tag es como un commit diferente y por tanto su autor es el autor de la etiqueta. Lo del asterisco no lo veo claro

Si alguien que lo sabe explicar mejor por favor que lo haga en los comentarios 😀


Automatización

Así sin darle muchas vueltas a la cabeza se me ocurren tres maneras de automatizar la creación del registro de cambios:

  • Si estamos usando un editor específico para LaTeX, podemos hacer que el git for-each-ref se ejecute delante del compilador creando una nueva herramienta de compilación.

  • Si compilamos a pelo o con Pandoc podemos añadir esa orden al Makefile.

  • Si queremos aprender más de git podemos escribir un hook.

Como las dos primeras yo ya las sé hacer y vosotros también (y si no me preguntáis que para algo hay comentarios), vamos a hacer la tercera que es la más raruna.

Un hook de git

Un hook es un programilla que se ejecuta automáticamente cuando ocurre determinada acción, como un commit o un push, ya sea justo antes de la acción o justo después. Por ejemplo, un hook pre-commit se ejecutará antes de ejecutar el commit en sí mismo, lo que es útil para verificar cosas antes de commitear. Yo he hecho uno post-commit para investigar pero igual no es la mejor opción. Para ello he creado el archivo .git/hooks/post-commit y he escrito dentro nuestra magnífica línea:

#!/bin/sh
git for-each-ref --format="%(refname:short) & %(authordate:short) & %(subject) \\\\" refs/tags > log.tex

No os olvidéis de darle permisos de ejecución, que me he sentido bastante imbécil cuando me he dado cuenta de por qué no estaba funcionando…

Ahora gracias a mi habilidad con git y LaTeX, siempre que hago un commit se me actualiza el registro de cambios él solo y yo me creo muy lista.

Otras opciones

He barajado también otras opciones que al final no he usado pero que a vosotros os pueden interesar así que las repaso someramente aquí.

Un comando propio

También podríamos definir nuestro propio comando de LaTeX:

\newcommand{log}[ARGUMENTOS]{DEFINICIÓN}

y extraer los datos según ese formato concreto. Uso de ejemplo la primera orden que hemos creado que es más corta y se entiende mejor:

git log --date=short --pretty=format:'\log{%ad}{%s}' > log.tex

Paquetes

En cuanto a paquetes tenemos un montón de opciones pero no me convence ni uno. Casi todo lo que he visto tiene relación con incluir al pie o en una marca de agua la versión actual, como vc y gitinfo2. Para el tema del registro de cambios está el programilla latex-git-log que puede que yo sea corta de entendederas pero me cuesta comprender y gitlog, que por algún motivo extrae la información de los commits como si fuera una bibliografía.

Lo que si me ha parecido interesante es fusionar el paquete vhistory con el tema de exportar con git log. Si usamos vhistory en solitario, tenemos que meter el histórico a mano pero teniendo en cuenta que una nueva línea en el registro se introduce mediante el comando \vhEntry de la siguiente manera:

\vhEntry{VERSIÓN}{FECHA}{AUTOR}{CAMBIOS}

podemos trucar nuestra superlínea para que nos cree la lista de versiones que luego incluiremos en el lugar adecuado con \input:

git for-each-ref --format="\vhEntry{%(refname:short)}{%(authorname)}{%(authordate:short)}{%(subject)}" refs/tags > log.tex

Lo chulo de este paquete es que nos da herramientas para utilizar la información del registro de cambios a lo largo del documento. Como he dicho arriba, no me lo he analizado en mucho detalle, pero me parece interesante este enfoque.


Nada más por hoy señores míos, hurguen y compartan sus experiencias con sus congéneres.

Referencias

Generate your changelogs with Git log

Including git commit history in a LaTeX document

Printing git information in Latex

How does one git log tagged commits only?

Best practice for maintaining change history in tex

Including Git Revision Identifiers in LaTeX

Git + LaTeX + gitinfo =


Esta es la música que tenía al descubrir toda la historieta.

Anuncios

7 pensamientos en “Lo que he aprendido: registro de cambios en un documento LaTeX con git

  1. ekaitzzarraga

    Yup,

    A mí me da problemas, no me pone la fecha.
    Si en lugar de poner authordate ponemos *authordate me funciona y con taggerdate también.

    De la documentación:

    If fieldname is prefixed with an asterisk (*) and the ref points at a tag object, the value for the field in the object tag refers is used.

    Yo creo que para lo que nos ocupa lo mejor es ponerle el * porque necesitamos que nos coja la información del tag. Aunque, sinceramente, no entiendo muy bien la documentación y las diferencias.

    Saludos

    Responder
    1. ekaitzzarraga

      Creo que está relacionado con el tipo de tag, a mí no me mostraba porque tengo tags con mensaje.
      Con tags lightweight funciona al revés… menuda cosa.

      Responder
  2. Pingback: Documentación para un proyecto con Markdown y Pandoc | Onda Hostil

  3. Pingback: En qué ando: abril | Onda Hostil

  4. Pingback: Curso no convencional de LaTeX: abramos la caja de herramientas | Onda Hostil

¡Opina sin miedo! (Puedes usar Markdown)

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s