答案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}