简体   繁体   English

c头文件递归git log漂亮格式

[英]c header file recursive git log pretty format

I am trying to combine git version information into one c header file.我正在尝试将 git 版本信息合并到一个 c 头文件中。

try this script试试这个脚本

#!/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}

but the output is as follows但输出如下

$ ./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>...]'

What would you like to do?你想干什么?

The immediate cause of the error is here, as Renaud Pacalet noted in a comment :正如Renaud Pacalet 在评论中指出的那样,错误的直接原因就在这里:

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

The txt_format variable is set, a few lines earlier, to a string that includes spaces. txt_format变量在几行之前设置为包含空格的字符串。 When bash (or any POSIX shell) interpolates the string into ${txt_format} , these spaces cause word-breaking, so that you're running:当 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

What you had intended to run is:打算运行的是:

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

which requires using double quotes around the expansion of $txt_format (and, as the same comment notes, removing the single quotes from the setting).这需要在$txt_format的扩展周围使用双引号(并且,正如相同的注释所述,从设置中删除单引号)。 Note that any quotes—single or double—embedded in the text expansion do not affect the word-breaking of the expansion;请注意,文本扩展中嵌入任何引号(单引号双引号)都不会影响扩展的分词; the word-breaking is determined solely by whether the expansion itself is quoted.断词完全取决于扩展本身是否被引用。 (In effect, the quotes are "painted over" during the expansion so that they cannot affect the result: they don't look like quotes any more. 1 The variable is expanded, words get broken up, and then only towards the end is the "paint" removed from the quotes so that git will see them as quote characters.) (实际上,引号在扩展过程中被“涂上”,因此它们不会影响结果:它们看起来不再像引号了。1变量被扩展,单词被分解,然后只有接近结尾是从引号中删除的“油漆”,以便git将它们视为引号字符。)

It is, however, worth noting something else about submodules that eliminates the need to put in one hash per submodule, and that is this: By design, the commit hash ID in the superproject completely determines all the commit hash IDs in each submodule.然而,值得注意的是关于子模块的其他一些事情,它消除了每个子模块放入一个哈希的需要,那就是:根据设计,超级项目中的提交哈希 ID 完全决定了每个子模块中的所有提交哈希 ID。 After cloning the superproject, you git checkout or git switch -to the selected commit hash ID in the superproject.克隆超级项目后,您git checkoutgit switch - 到超级项目选定的提交哈希 ID。 Then you run git submodule update --init (with --recursive if needed), and the commit that you selected in the superproject has, in each of its gitlink entries that controls each submodule, the raw hash ID of that submodule.然后您运行git submodule update --init (如果需要,使用--recursive ),并且您在超级项目中选择的提交在其控制每个子模块的每个gitlink条目中都有该子模块的原始哈希 ID

It's possible to violate this design assumption (in which case you would in fact need every submodule hash ID), but you should never do it for any official build.可能会违反此设计假设(在这种情况下,您实际上需要每个子模块哈希 ID),但您永远不应该为任何官方构建这样做。 So storing the hash ID of the superproject alone should normally suffice.因此,单独存储超级项目的哈希 ID 通常就足够了。

It's also worth mentioning a few other items:还值得一提的是其他一些项目:

  • To get the full raw hash ID of the current commit, simply run git rev-parse HEAD .要获取当前提交的完整原始哈希 ID,只需运行git rev-parse HEAD There's no need to run git log --format=%H -n 1 .无需运行git log --format=%H -n 1 (Of course if you want some additional decoration, you'll need to add that, and git log 's formatting directives are one way to add it, so at this point it becomes kind of six-of-one half-a-dozen-of-the-other.) (当然,如果你想要一些额外的装饰,你需要添加它,而git log的格式化指令是添加它的一种方式,所以此时它变成了六合一的六分之一-另一个。)

  • The git describe command is the usual way most people choose to produce a "human-oriented" hash ID for version consumption. git describe命令是大多数人选择为版本消费生成“面向人的”哈希 ID 的常用方式。 Just how human-oriented this is (or could possibly be) is a bit of an open question, but when building a release from a release tag, this gives you a very nice v2.10 or whatever.这是(或可能)如何以人为本是一个悬而未决的问题,但是当从发布标签构建发布时,这会为您提供一个非常好的v2.10或其他版本。

So, usually we just want:所以,通常我们只想要:

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

or similar as our "version generator".或类似于我们的“版本生成器”。


1 In ancient (non-8-bit-clean) versions of /bin/sh this "painting over" was done by setting the high bit of every character, so that quotes and glob characters were no longer ' or * or whatever. 1/bin/sh的古代(非 8 位清洁)版本中,这种“覆盖”是通过设置每个字符的高位来完成的,因此引号和全局字符不再是'*或其他任何东西。 Then the 0x80 bit was removed just before the execve system call.然后在execve系统调用之前删除了0x80位。 Since shells now have to allow all these byte values to pass through, this trick is no longer possible, but it still describes the behavior: you just have to imagine something other than c | 0x80由于 shell 现在必须允许所有这些字节值通过,所以这个技巧不再可能,但它仍然描述了行为:你只需要想象除c | 0x80之外的其他东西。 c | 0x80 happening. c | 0x80发生。 For instance, the shell could store the bytes in short variables and use c | 0x100例如,shell 可以将字节存储在short变量中并使用c | 0x100 c | 0x100 , and then use c & 0xff to strip off the "paint".) c | 0x100 ,然后使用c & 0xff剥离“油漆”。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM