# How to include the current Git commit ID and branch in my document?

I use Git to track changes on my TEX files. When producing a PDF, it would be nice to include the current branch and commit ID somewhere in the document (e.g. on the title page or in a footer).

I know that the package gitinfo2 exists but I'd rather avoid adding any hooks to Git. Besides, I am aware of this question but I would prefer a solution that does not require enabling \write18.

Given that the name of the current branch can be found in .git/HEAD and the current commit ID is stored in .git/refs/heads/[name of branch], is it possible to embed this information in the final document?

• I'm writing this self-answered Q&A because it took me a while to figure this out. Hope it will help others in the future.
– CL.
Oct 16, 2018 at 11:10
• despite the question saying you wanted an alternative to gitinfo, there is a big overlap so I added that tag Oct 16, 2018 at 11:34

As stated in the question, the branch name can be extracted from .git/HEAD and given [branch name], the commit ID can be found in .git/refs/heads/[branch name].

The package catchfile provides the command \CatchFileDef, which allows us to read .git/HEAD into a macro. As HEAD has no file extension, MiKTeX users have to add a trailing dot to the file name:

\CatchFileDef{\headfull}{.git/HEAD.}{}


This assigns something like ref: refs/heads/master  to \headfull. As this string has a trailing whitespace character, we use \StrGobbleRight from the xstring package to trim it:1

\StrGobbleRight{\headfull}{1}[\head]


In order to extract only the branch name (master in the example) from this string, we can use \StrBehind:

\StrBehind[2]{\head}{/}[\branch]


This saves the branch name in \branch. Finally, we can use \CatchFileDef again, to save the commit ID in \commit:

\CatchFileDef{\commit}{.git/refs/heads/\branch.}{}


There are some edge cases where .git/refs/heads/\branch. does not exist: After running git pack-refs (which is a side effect of git gc --aggressive, for example), the heads are packed into the file .git/packed-refs instead of individual branchname files. As a workaround, check if the file exists before trying to read it:

\IfFileExists{.git/refs/heads/\branch.}{%
\newcommand{\commit}{\dots~(in \emph{packed-refs})}}


As a fallback, this creates the (not-so-useful) output "... (in packed-refs)" instead of a commit ID – but this only lasts until the next commit, when the file heads/branchname is recreated for the affected branch. (A more ambitious workaround could parse packed-refs, of course.)

# Full MWE:

\documentclass{article}

\usepackage{xstring}
\usepackage{catchfile}

\newcommand{\commit}{\dots~(in \emph{packed-refs})}}

\begin{document}
This revision: \texttt{\commit} on branch \texttt{\branch}.
\end{document}


## Sample output:

This revision: d92dc1386e48e04ceecb85461ed3b232146e6a32 on branch master.

1 Using the last optional argument of \StrGobbleRight (name) to assign the trimmed string to a macro (\head) is necessary to allow further manipulation of the string using the xstring functions – see here for a discussion.

• Is it correct that catchfile is currently a no-go with lualatex? Dec 11, 2018 at 0:47
• Sorry, I've never been using lualatex yet.
– CL.
Dec 11, 2018 at 6:39
• @ingli I didn't test this yet, but I think you should be able to modify the approach here.
– CL.
Jul 7, 2020 at 9:09
• @SeF It (still) works for me. Would you mind sharing a reproducible example, maybe even a minimal Github repository?
– CL.
Jul 28, 2021 at 14:15
• @SeF Yes, I think I see your problem. But I'd say this is "natural": You need to commit etc. before you compile. … … Ok, now I think I understand: You're commiting the PDF as well? Agreed, this won't work. But IMHO, you should "gitignore" the PDF anyway and only commit the source files. And then the problem should become a non-issue automatically. ;-)
– CL.
Jul 28, 2021 at 14:43

A no-package approach (tested on mac os, modify it for Windows regarding extra needed dot perhaps) based on @CL.'s answer.

\documentclass{article}

\newcommand\branch{}
\newcommand\commit{}

\makeatletter\let\myfilehandle\@inputcheck\makeatother

\begingroup\endlinechar-1
\endgroup
\closein\myfilehandle

\newcommand\GetBranch{}

\begingroup\endlinechar-1
\endgroup
\closein\myfilehandle

\begin{document}
\branch+++

\commit+++

This revision: \texttt{\commit} on branch \texttt{\branch}.
\end{document}


Package getcommit:

\ProvidesPackage{getcommit}[2018/10/16 get current commit and branch (JFB)]

\@ifundefined{branch}{}
{\PackageWarning{getcommit}{ATTENTION!^^J
\@spaces\@spaces\string\branch\space macro was already
defined. Overwritten.}}
\@ifundefined{commit}{}
{\PackageWarning{getcommit}{ATTENTION!^^J
\@spaces\@spaces\string\commit\space macro was already
defined. Overwritten.}}

\begingroup\endlinechar-1
\endgroup
\closein\@inputcheck

\begingroup\endlinechar-1
\endgroup
\closein\@inputcheck
\endinput


Example of use:

\documentclass{article}

\usepackage{getcommit}

\begin{document}
+++\branch+++

+++\commit+++

%\frenchspacing
This revision: \texttt{\commit} on branch \texttt{\branch}.
\end{document}

• is there an available scratch file handle for read operations in LaTeX, avoiding a \newread here?
– user4686
Oct 16, 2018 at 12:16
• There is \@inputcheck used by the kernel in \IfFileExists. Oct 16, 2018 at 12:29
• Quite nice and it works on windows. But imho for a real package it should try to find the info also in parent folders (imho gitinfo2 looks 4 levels up by default). Oct 16, 2018 at 13:44
• But miktex really needs the period at the end ... Oct 16, 2018 at 13:54
• @UlrikeFischer is there any test allowing package to know that this is executed under MikTeX?
– user4686
Oct 16, 2018 at 14:04

We can use \input instead \read primitive:

\def\gitdir{.git/}
\def\readgitbranchA #1 #2 {\def\gitbranch{#2}}

Now, the commit ID is in "\gitcommit" macro.


If you are using latexmk, you can use an alternative approach to intialize gitinfo2, that does not require git hooks (https://github.com/rbarazzutti/gitinfo2-latexmk).

Setup:

$git submodule add https://github.com/rbarazzutti/gitinfo2-latexmk gitinfo2-latexmk$ echo "do './gitinfo2-latexmk/gitinfo2.pm';" >> latexmkrc


Usage:

\usepackage[mark]{gitinfo2}