2、版本控制联动:Git Hook触发自动化编译,提交即构建
说实话,很多嵌入式团队还在用手动编译的老路子。改完代码,点一下编译,等几分钟,再烧录。一天下来,光等编译就耗掉大把时间。更可怕的是——有人忘了编译就提交,结果队友拉下来一跑,直接报错。
Git Hook 就是来解决这个问题的。它能在特定事件发生时自动执行脚本。我们最常用的,就是 pre-commit 和 post-commit 这两个钩子。
2.1 什么是 Git Hook?
Git Hook 本质上是存放在 .git/hooks/ 目录下的脚本文件。Git 在执行某些操作前或后,会自动查找并执行对应的脚本。我习惯把它们想象成「守卫」——在代码提交前检查一遍,不合格就拦下来。
| 钩子名称 | 触发时机 | 常用场景 |
|---|---|---|
| pre-commit | 执行 git commit 之前 |
代码风格检查、静态分析、单元测试 |
| commit-msg | 提交信息写入前 | 校验提交信息格式是否符合规范 |
| post-commit | 提交完成后 | 触发 CI 构建、通知、自动部署 |
| pre-push | git push 之前 |
运行完整测试套件、检查分支权限 |
你看,每个钩子都有自己的职责。我个人最看重 pre-commit 和 post-commit 这两个,因为它们直接关系到「提交即构建」这个目标。
2.2 搭建 pre-commit 钩子:提交前先编译
先说说 pre-commit。这个钩子跑在提交之前,如果脚本返回非零值,提交就会被中断。说白了,就是「编译不过就别想提交」。
我在一个 STM32 项目里是这样写的:
#!/bin/bash
# .git/hooks/pre-commit
echo "🔨 开始预提交编译检查..."
# 进入项目根目录
cd "$(git rev-parse --show-toplevel)"
# 清理上次编译产物
make clean
# 执行编译
make -j4
# 检查编译结果
if [ $? -ne 0 ]; then
echo "❌ 编译失败!请修复错误后再提交。"
exit 1
fi
echo "✅ 编译通过,可以提交。"
exit 0
嗯,这里要注意一点:这个脚本必须要有可执行权限。我见过有人写好了脚本,但忘了 chmod +x,结果钩子根本没跑。
我曾经在一个团队里遇到过这种情况:pre-commit 脚本里直接调用了
make,但开发机上没装交叉编译工具链。结果所有人都提交不了。所以,钩子脚本要考虑到不同开发环境。可以在脚本开头加个环境检测,工具链不存在就跳过编译检查,只做语法检查。
2.3 搭建 post-commit 钩子:提交后自动构建
pre-commit 是「守门员」,post-commit 就是「快递员」。提交成功后,它负责把代码送到 CI 服务器上,触发自动化构建。
我常用的做法是:post-commit 钩子调用一个远程 API,告诉 Jenkins 或 GitLab CI 去拉取最新代码并开始构建。
#!/bin/bash
# .git/hooks/post-commit
# 获取当前分支名
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# 只对 master 和 release 分支触发远程构建
if [ "$BRANCH" = "master" ] || [ "$BRANCH" = "release" ]; then
echo "🚀 触发远程 CI 构建..."
# 调用 Jenkins API
curl -X POST "http://ci-server:8080/job/embedded-build/buildWithParameters?token=my-token&branch=$BRANCH"
if [ $? -eq 0 ]; then
echo "✅ 构建已触发,请查看 CI 控制台。"
else
echo "⚠️ 触发失败,请手动检查 CI 服务。"
fi
fi
你可以在 post-commit 里加上一个「本地快速构建」步骤。比如只编译改动的文件,而不是全量编译。这样提交后能立刻得到一个初步的编译结果,等 CI 那边跑完整构建时,你已经知道大概率没问题了。
2.4 提交即构建的完整流程
把 pre-commit 和 post-commit 串起来,就形成了「提交即构建」的闭环。我画了一张流程图,你看一眼就明白了:
这个流程跑起来后,团队里再也没有「编译不过的提交」了。每次提交都意味着代码至少能在本地编译通过,CI 那边再跑一遍完整构建和测试,双重保障。
2.5 进阶:使用 husky 管理钩子
手动写钩子脚本有个麻烦——它们存在 .git/hooks/ 目录下,不会被版本控制。换台机器就得重新配。我推荐用 husky 这个工具来管理。
Husky 可以把钩子配置写在 package.json 或 .husky/ 目录里,随项目一起提交。团队成员 clone 后,执行 npm install 或 husky install 就能自动激活钩子。
// package.json 中的配置示例
{
"husky": {
"hooks": {
"pre-commit": "make check && make -j4",
"post-commit": "curl -X POST http://ci-server/build",
"pre-push": "make test"
}
}
}
- pre-commit 钩子做「编译检查」,失败则阻止提交
- post-commit 钩子做「触发构建」,成功后通知 CI
- 钩子脚本要放在版本控制中(通过 husky 或符号链接)
- 考虑不同开发环境,脚本里加工具链检测
2.6 常见问题与解决方案
实际落地时,你可能会遇到几个坑。我列出来,你直接拿去用:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 钩子没执行 | 脚本没有可执行权限 | chmod +x .git/hooks/pre-commit |
| 编译太慢,提交卡住 | 全量编译耗时过长 | 只编译改动文件,或使用增量编译 |
| CI 触发失败 | 网络不通或 API 地址错误 | 加超时重试机制,失败时输出日志 |
| 团队成员没配钩子 | 钩子不在版本控制中 | 使用 husky 或写脚本自动部署钩子 |
我记得有一次,团队里新来了个同事,提交代码时 pre-commit 一直报错。排查了半天,发现是他电脑上的 Makefile 路径和项目结构对不上。后来我在钩子脚本里加了个 git rev-parse --show-toplevel 来动态获取根目录,问题就解决了。
说白了,Git Hook 就是个「自动化开关」。你把它和编译流程绑在一起,就能做到「提交即构建」。不用再手动点编译按钮,也不用担心有人忘了编译就提交。代码质量上去了,团队效率也高了。