c头文件递归git日志漂亮的格式



我正在尝试将git版本信息合并到一个c头文件中。

试试这个脚本

#!/bin/bash
curr_path=$(pwd)
submodule_path_array=($(git submodule foreach "git submodule foreach pwd && pwd" | grep "${curr_path}*"))
echo "#ifndef __GITVER_H__" > ${curr_path}/gitver.h
echo "#define __GITVER_H__" >> ${curr_path}/gitver.h
for path in ${submodule_path_array[@]}
do
cd ${path}
txt_format="'#define COMMIT_$(basename "$path") "%H"%n'"
echo -e ${txt_format}
git log --pretty=tformat:${txt_format} -n 1 >> ${curr_path}/gitver.h
done
echo "#endif" >> ${curr_path}/gitver.h
cd ${curr_path}

但是输出如下

$ ./git_ver.sh
'#define COMMIT_submodule0 "%H"%n'
fatal: ambiguous argument 'COMMIT_submodule0': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
'#define COMMIT_submodule1 "%H"%n'
fatal: ambiguous argument 'COMMIT_submodule1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
'#define COMMIT_submodule2 "%H"%n'
fatal: ambiguous argument 'COMMIT_submodule2': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

你想做什么?

这个错误的直接原因在这里,正如Renaud Pacalet在评论中指出的:

git log --pretty=tformat:${txt_format} -n 1 >> ${curr_path}/gitver.h

在前面几行中,txt_format变量被设置为包含空格的字符串。当bash(或任何POSIX shell)将字符串插入${txt_format}时,这些空格会导致断字,因此您将运行:

git log --pretty=tformat:'#define COMMIT_submodule0 "%H"%n' -n 1

你让想要运行的是:

git log --pretty=tformat:#define COMMIT_submodule0 "%H"%n -n 1

需要在$txt_format的展开部分周围使用双引号(并且,正如同一注释所指出的,从设置中删除单引号)。注意,在文本展开中,任何单引号或双引号都不会影响展开的断行;断字完全取决于展开本身是否被引用。(实际上,引号被"涂上"了。在展开期间,这样它们就不会影响结果:它们看起来不再像引号了。1变量被展开,单词被分解,然后只有在末尾是"paint"从引号中删除,以便git将它们视为引号字符。)

然而,值得注意的是,关于子模块的其他一些事情消除了在每个子模块中放入一个哈希的需要,那就是:根据设计,超项目中的提交哈希ID完全决定了每个子模块中的所有提交哈希ID。克隆超级项目后,将git checkoutgit switch添加到超级项目中选择的提交哈希ID。然后运行git submodule update --init(如果需要,可以使用--recursive),您在超级项目中选择的提交在其控制每个子模块的gitlink条目中都包含该子模块的原始哈希ID

。有可能违反这种设计假设(在这种情况下,您实际上需要每个子模块哈希ID),但您不应该在任何正式版本中这样做。因此,仅存储超级项目的哈希ID通常就足够了。

还值得一提的是:

  • 要获取当前提交的完整原始哈希ID,只需运行git rev-parse HEAD。没有必要运行git log --format=%H -n 1。(当然,如果你想要一些额外的装饰,你需要添加它,git log的格式指令是添加它的一种方式,所以在这一点上,它变成了一种半打其他的六。)

  • git describe命令是大多数人通常选择的生成"以人为本"的;用于版本消耗的哈希ID。这是如何以人为本的(或者可能是)是一个悬而未决的问题,但是当从一个发布标签构建一个发布时,这给了你一个非常好的v2.10或其他什么。

通常我们只需要:

printf "#ifndef VERSIONn#define VERSION "%s"n#endifn" 
$(git describe --tags --always --dirty) > version.h

或类似于我们的"版本生成器"。


1/bin/sh的古代(非8-bit-clean)版本中,此"绘画覆盖";是通过设置每个字符的高位来完成的,所以引号和glob字符不再是'*或其他什么。然后在execve系统调用之前删除0x80位。由于shell现在必须允许所有这些字节值通过,这个技巧不再可能了,但它仍然描述了行为:您只需要想象发生的不是c | 0x80的事情。例如,shell可以将字节存储在short变量中并使用c | 0x100,然后使用c & 0xff去掉"油漆">

最新更新