完整 MWE:

完整 MWE:

我使用 Git 来跟踪 TEX 文件的更改。生成 PDF 时,最好在文档的某个位置(例如在标题页或页脚中)包含当前分支和提交 ID。

我知道这个包裹gitinfo2存在,但我宁愿避免在 Git 中添加任何钩子。此外,我知道这个问题但我更喜欢不需要启用的解决方案\write18

假设可以在中找到当前分支的名称,.git/HEAD并且当前提交 ID 存储在中.git/refs/heads/[name of branch],是否可以将此信息嵌入到最终文档中?

答案1

正如问题所述,可以从中提取分支名称.git/HEAD并给出[branch name],可以在中找到提交ID .git/refs/heads/[branch name]

包裹catchfile提供命令\CatchFileDef,允许我们读.git/HEAD入宏。由于HEAD没有文件扩展名,MiKTeX 用户必须添加尾随点文件名为:

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

这将类似ref: refs/heads/master地将某些内容分配给\headfull。由于此字符串末尾有一个空格字符,因此我们\StrGobbleRight使用字符串修剪包:1

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

为了master从该字符串中仅提取分支名称(在示例中),我们可以使用\StrBehind

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

这会将分支名称保存在 中\branch。最后,我们可以\CatchFileDef再次使用 将提交 ID 保存在 中\commit

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

有一些.git/refs/heads/\branch.不存在的极端情况:运行后git pack-refs(这是git gc --aggressive例如,头部被打包到文件中,.git/packed-refs而不是单独的branchname文件中。解决方法是,在尝试读取文件之前检查文件是否存在:

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

作为后备,这将创建(不太有用的)输出“...(在打包引用)”而不是提交 ID —— 但这只会持续到下一次提交,heads/branchname即为受影响的分支重新创建文件时。(packed-refs当然,一个更雄心勃勃的解决方法可以解析。)

完整 MWE:

\documentclass{article}

\usepackage{xstring}
\usepackage{catchfile}

\CatchFileDef{\headfull}{.git/HEAD.}{}
\StrGobbleRight{\headfull}{1}[\head]
\StrBehind[2]{\head}{/}[\branch]
\IfFileExists{.git/refs/heads/\branch.}{%
    \CatchFileDef{\commit}{.git/refs/heads/\branch.}{}}{%
    \newcommand{\commit}{\dots~(in \emph{packed-refs})}}

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

示例输出:

本次修订:d92dc1386e48e04ceecb85461ed3b232146e6a32在分支上 master


1\StrGobbleRight使用( )的最后一个可选参数name将修剪后的字符串分配给宏 ( \head) 是必要的,以便使用函数进一步操作字符串xstring- 请参阅这里进行讨论。

答案2

基于@CL.的答案的无包装方法(在mac os上测试,可能针对Windows修改它以添加额外需要的点)。

\documentclass{article}

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


\makeatletter\let\myfilehandle\@inputcheck\makeatother

\openin\myfilehandle=.git/HEAD\relax

\begingroup\endlinechar-1
  \global\read\myfilehandle to \dotGitHEAD
\endgroup
\closein\myfilehandle

\newcommand\GetBranch{}
\def\GetBranch ref: refs/heads/#1\relax{\renewcommand{\branch}{#1}}

\expandafter\GetBranch\dotGitHEAD\relax

\openin\myfilehandle=.git/refs/heads/\branch\relax

\begingroup\endlinechar-1
  \global\read\myfilehandle to \commit
\endgroup
\closein\myfilehandle

\begin{document}
\branch+++

\commit+++

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

在此处输入图片描述



包裹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.}}

\openin\@inputcheck=.git/HEAD\relax

\begingroup\endlinechar-1
  \global\read\@inputcheck to \getcommit@HEAD
\endgroup
\closein\@inputcheck

\def\getcommit@GetBranch ref: refs/heads/#1\relax{\def\branch{#1}}

\expandafter\getcommit@GetBranch\getcommit@HEAD\relax

\openin\@inputcheck=.git/refs/heads/\branch\relax

\begingroup\endlinechar-1
  \global\read\@inputcheck to \commit
\endgroup
\closein\@inputcheck
\endinput

使用示例:

\documentclass{article}

\usepackage{getcommit}

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

+++\commit+++

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

答案3

我们可以使用原始\input方法\read

\def\gitdir{.git/}
\def\readgitcommitA #1 {\def\gitcommit{#1}}
\def\readgitbranchA #1 #2 {\def\gitbranch{#2}}
\def\readgitcommit{\expandafter\readgitbranchA \input \gitdir HEAD
  \expandafter\readgitcommitA \input \gitdir\gitbranch\relax}

\readgitcommit

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

答案4

如果你正在使用latexmk,你可以使用另一种方法进行初始化gitinfo2,即不是需要 git hooks (https://github.com/rbarazzutti/gitinfo2-latexmk)。

设置:

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

用法:

\usepackage[mark]{gitinfo2}

相关内容