Monthly Archives: May 2011

Including Git Revision Identifiers in LaTeX

I keep most of my LaTeX source files under the revision control system Git.

Stupid git


Git is opinionated software. It allows you to do many things, but others run counter to its dogmas. In particular, Git does not modify source files.

Other systems do. For example, you can ask Subversion to replace the placeholder $Revision in the committed source file with the latest revision number. This is useful for displaying revision numbers or dates in your LaTeX documents, for example.

From Git’s perspective, modification of source file is pure evil. Not only is this feature absent from Git, but the very request betokens moral corruption.

From Git’s perspective, the client programme (in this case, LaTeX) is responsible for including revision information in the output. Git humbly makes that information available. But it does not modify the source.

Stephan Hennig’s vc bundle consists of a number of scripts that extract revision information from various version control systems, including Git, and make it available as LaTeX macros. The information is taken from a separate, automatically generated input file vc.tex, so that the main LaTeX source file remains untouched by Git.

This shifts the problem to the generation of vc.tex. I’ve played around with various solutions based on Makefiles, and here is my current setup.

The vc.tex file is automatically generated and defines three LaTeX macros. Typically, it looks like this:

%%% This file is generated by Makefile.
%%% Do not edit this file!
%%%
\gdef\GITAbrHash{f61c739}
\gdef\GITAuthorDate{Fri May 13 10:34:51 2011 +0200}
\gdef\GITAuthorName{Thore Husfeldt}

The main LaTeX source includes the vc.tex file in the preamble and can now freely use these macros. For example, the revision information can be included in a footnote on the title page.

\documentclass{article}
...
\input{vc.tex}
...
\begin{document}
\maketitle
\let\thefootnote\relax
\footnotetext{Base revision~\GITAbrHash, \GITAuthorDate, \GITAuthorName.}
...

The responsibility of producing an up-to-date vc.tex rests on the Makefile:

latexfile = main

all: $(latexfile).pdf

$(latexfile).pdf : $(latexfile).tex vc.tex
	while (pdflatex $(latexfile) ; \
	grep -q "Rerun to get cross" $(latexfile).log ) do true ; \
	done

vc.tex: .git/logs/HEAD
	echo "%%% This file is generated by Makefile." > vc.tex
	echo "%%% Do not edit this file!\n%%%" >> vc.tex
	git log -1 --format="format:\
		\\gdef\\GITAbrHash{%h}\
		\\gdef\\GITAuthorDate{%ad}\
		\\gdef\\GITAuthorName{%an}" >> vc.tex

The interesting rule is the last one. It runs git log to produce vc.code. The hardest thing for me was to get the dependencies right. I think I’ve got it now. The input file vc.tex needs to be regenerated whenever it predates the last commit. As far as I understand the Git internals, the modification time of .git/logs/HEAD should give me a reliable timestamp for when the last commit happened, so I made my rule for vc.tex depend on that.

Of course, it’s a cheap operation, so we could generate vc.tex anew every time we run pdflatex. But then every call to make would recompile the source (because vc.tex has changed). To avoid that, we could leave vc.tex out of the dependencies for $(latexfile).pdf. But then a commit (which modifies the revision number but not any source files) would not lead to an automatic recompile. The LaTeX document would only display new revision information whenever it is edited after that revision.

If there’s a cleaner way of checking for “is vc.tex outdated compared to the Git repository”, please tell me.

TODO: Make the LaTeX document reflect that it corresponds to uncommitted edits after the latest revision. This should be doable by comparing the modification times of the LaTeX source files and .git/logs/HEAD. A cruder way is to let git status tell the Makefile if working directory is “clean”.

UPDATE (21 Feb 2012): Since this post was written, various other approaches have appeared. (Thanks to the commenters for pointing them out.) The idea of using a post-commit hook instead of a Makefile is now on CTAN: gitinfo package.

Generation Z and the Alphabet

I teach generation Z, people who are now in their early twenties.

Generation Z follows Generation Y, which follows Generation X.

What will we call the next generation? We’ve run out of letters! “Generation [”?

Well, it doesn’t matter. Read on…

I was reviewing old exam questions in my introductory algorithms and data structures class. Here’s the question:

This looks innocent enough. However, several students were openly annoyed by this question.

What’s the problem? It has nothing to do with priority queues or heap order or anything else algorithmic. If you aren’t generation Z, you’ll never guess.

They asked me to please use numbers instead of letters. Why? I turns out that comparison between letters is no longer constant time! As one student put it, with a straight face, it’s really hard to determine if, say, Q is higher or lower than some other letter. Helpful students sagely suggested to their fellow students to just start by making a list of the alphabet on a separate piece of paper for this type of exercise. This was met with earnest nodding.

It was quite clear that I had made this question needlessly difficult by making it about letters.

This is a sterling example of a skill that is utterly natural to my generation, who has looked things up alphabetically countless times. I have no harder time comparing M and S than I have comparing 5 and 13. But, of course, Generation Z has never looked anything up alphabetically. It‘s an utterly useless skill honed in the olden days of outdated information technology, like knowing how a slide rule works or typing on a T9 mobile phone keypad. Generation Z finds this as hard (and as useless) as I find it comparing Ψ and Φ. I can do it, because I memorised the Greek alphabet with I was eight or so, and can still rattle it off in the right order. But it takes linear time in the size of the alphabet.

So, from now on, I guess I use plain old numbers in this type of exam questions.

Also, the generations following Generation Z can be safely called Generation W, V, U, etc. Nobody will notice.

Also, I feel old.