awk 处理 Git 提交信息生成 Release Note
Posted 1bite
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了awk 处理 Git 提交信息生成 Release Note相关的知识,希望对你有一定的参考价值。
发布软件时通常都会写 Release Note,但每次从头手打也有点累,可以考虑从 Git 的提交历史中自动生成。
Git 提交信息一般是三段式结构,段落之间使用空行隔开:
<subject>
// 空行
<body>
// 空行
<trailers>
subject
和 body
自不必多说,trailers
中一般是一条条键 -- 值对构成的信息,键和值由冒号 :
分隔。比如 Git 的 Commiter:
就可以视为一条 trailer
,Gerrit 代码审查通过后,也会在 Git 提交消息中添加 Reviewed-by:
和 Tested-by:
之类的 trailer
。
现假设提交信息中的 trailers
包含 Type
和 Issue
字段,分别表示类别(NewFeature, BugFix 之类)和 BUG 编号(GitHub 上的 issue 编号或者内部系统的 BUG 编号):
Fixed a crash
- blahblah
- blahblahblah
Type: BugFix
Issue: issue-120
就可以结合 git log
和 awk
生成 Rlease Note:
git log --format=\'%(trailers:key=Type,valueonly,separator=%x20)%x1c%s [%(trailers:key=Issue,valueonly,separator=,)]\' $FROM..HEAD | awk -F "\\034" \'
gsub(/\\[\\]$/, "", $2);
if (length($1) == 0) $1="MISC";
if (!($1 in item_count)) item_count[$1]=0;
items[$1, item_count[$1]]=$2;
item_count[$1]++;
END
for (k in item_count)
print k;
k2=k;
gsub(/./, "-", k2);
print k2
for (i=0; i<item_count[k]; i++) print "* "items[k, i];
print ""
\'
输出:
BugFix
------
* Fixed a typo
* Fixed a crash [issue-120]
NewFeature
----------
* Added some magic
选择使用
awk
处理git log
的输出是因为 linux 跟 macOS 都带这个软件,不需要额外安装依赖。
Git 2.22.0 及以上版本才支持按键值筛选trailers
。
在 Windows 系统上,可能没有办法直接运行 .sh 文件。但是如果安装了 Windows 版本的 Git,则会带一个 Git Bash(也带了 awk
!),这样就可以在 Git Bash 中运行 .sh 文件,也可以创建一个 .cmd 文件包装一下:
@ECHO off
SETLOCAL
CALL :FIND-PATH GITEXE_PATH git.exe
IF "%GITEXE_PATH%"=="" (
ECHO git.exe is not found on your system
EXIT /B 2
)
CALL :GET-DIR-NAME GITEXE_DIR "%GITEXE_PATH%"
CALL :GET-DIR-NAME GITEXE_DIR "%GITEXE_DIR:~0,-1%"
@"%GITEXE_DIR%bin\\bash.exe" release-note.sh %*
:FIND-PATH
SET "%~1=%~f$PATH:2"
EXIT /B
:GET-DIR-NAME
SET "%~1=%~dp2"
EXIT /B
上面的脚本只能把 release note 生成出来,如果可以直接添加到 changelog.md 就好了,可以把脚本做如下改动。
一,添加版本信息。添加一个变量 PROJ_VER
表示当前项目版本,以 maven 项目为例:
PROJ_VER=`./mvnw help:evaluate -Dexpression=\'project.version\' -q -DforceStdout|tail -n 1`
然后将这个变量暴露给 awk,在 awk 命令后面添加 -v PROJ_VER PROJ_VER
即可。
二,将版本和日期打印出来。在 awk 程序中添加 BEGIN
块:
BEGIN
"date +%Y-%m-%d"|getline date;
if (PROJ_VER == "") print "# "date;
else print "# "PROJ_VER" "date;
三,在 change.md 头部追加生成的内容:
# 生成临时文件
tempf=`mktemp $TEMP/changelog.md.XXXX`
touch changelog.md
# 将生成的内容与原 changelog.md 中的内容合并,保存到临时文件中,然后用临时文件替换当前文件即可
... | cat - changelog.md > $tempf && mv $tempf changelog.md
这样一顿操作下来,生成的 changelog.md 如下:
# 1.2.3 2023-03-31
BugFix
------
* Fixed a typo
* Fixed a crash [issue-120]
NewFeature
----------
* Added some magic
gradle中自动生成git提交信息
maven有一个git-commit-id插件,可以在打包的时候自动生成git commit相关的信息。对于查看版本是否发布正常非常有意义。
很遗憾gradle却没有。只有自己动手了。
- 首先编写一个gradle文件version-commit.gradle,定义一个gradle的task用于生成git信息,使用默认任务的方式defaultTasks或者在processResources任务之后执行。因为processResources就是专门处理资源文件的,所以生成git信息的文件在processResources之后生成就很合理。
import java.text.SimpleDateFormat
//使用默认task的方式嵌入
//defaultTasks 'versionCommit'
task("versionCommit")
versionCommit()
//在processResources之后执行
processResources.finalizedBy versionCommit
static def versionCommit()
Properties p = new Properties()
p.put("branch", getGitBranch())
p.put("commitId", getGitCommit())
p.put("commitAuthor", getGitCommitAuthor())
p.put("commitTime", getGitCommitTime())
p.put("packageTime", getCurrentTime())
p.store(new FileWriter("src/main/resources/version-commit.properties"), "generated by gradle git info plugin")
static def getGitCommit()
return 'git rev-parse --short HEAD'.execute().text.trim()
static def getGitCommitAuthor()
String commitId = getGitCommit();
String cmd = "git log --pretty=format:%an $commitId -1";
return cmd.execute().text.trim()
static def getGitCommitTime()
String commitId = getGitCommit();
String cmd = "git log --pretty=format:%ai $commitId -1";
return cmd.execute().text.trim();
static def getGitBranch()
return (System.getProperty("version") ?: "1.0-SNAPSHOT").replace("origin/", "")
static def getCurrentTime()
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
- 然后在build.gradle中引入,在打包的时候就会在类路径下生成version-commit.properties,保存最后一次提交相关的信息。
apply from: "$rootDir/version-commit.gradle"
- 然后在项目启动的时候读取version-commit.properties再打印出来即可。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.util.Properties;
/**
* 记录版本,每次发版打包的时候自动生成git相关信息
* gradle 生成git信息保存在类路径的version-commit.txt中
* @see https://blog.csdn.net/xxssyyyyssxx/article/details/128530853?spm=1001.2014.3001.5501
*/
public class VersionCommit
private static final Logger logger = LoggerFactory.getLogger(VersionCommit.class);
private static final String VERSION_COMMIT_FILE_NAME = "version-commit.properties";
//已实现的这些字段,还可以动态添加其他字段
public static final String BRANCH = "branch";
public static final String COMMIT_ID = "commitId";
public static final String COMMIT_AUTHOR = "commitAuthor";
public static final String COMMIT_TIME = "commitTime";
public static final String PACKAGE_TIME = "packageTime";
public static Map<String, String> fromFile()
Properties v = getVersionCommitInfo();
if(null != v)
HashMap<String, String> map = new HashMap<>(v.size());
for (String n : v.stringPropertyNames())
map.put(n, v.getProperty(n));
return map;
return null;
public static void print()
try
Map<String, String> map = fromFile();
if(null != map)
logger.info("start up successfully with version-commit: \\r\\n ", map);
catch (Exception e)
logger.error(e.getMessage(), e);
private static Properties getVersionCommitInfo()
String fileName = getCommitInfoFileName();
try (InputStream inputStream = VersionCommit.class.getClassLoader().getResourceAsStream(fileName);
)
Properties properties = new Properties();
properties.load(inputStream);
return properties;
catch (Exception e)
//有异常的时候返回null
return null;
/**
* 给一个修改的机会
*/
private static String getCommitInfoFileName()
String fileName = VERSION_COMMIT_FILE_NAME;
String v = System.getProperty("version.commit.file.name");
if(StrUtil.isNotEmpty(v))
fileName = v;
return fileName;
效果如下:
start up successfully with version-commit:
commitId=9ca343594, commitTime=2023-01-01 17:00:00 +0800, branch=feature-123, packageTime=2023-01-01 18:00:00, commitAuthor=someone
- 如果还有其他信息需要输入到version-commit.properties中,在versionCommit方法中加入即可。
以上是关于awk 处理 Git 提交信息生成 Release Note的主要内容,如果未能解决你的问题,请参考以下文章