应使用 git rev-parse --abbrev-ref HEAD 获取当前分支名,它在 detached HEAD 时返回 HEAD,可作为拦截信号;前缀添加应在 prepare-commit-msg 钩子中操作 COMMIT_EDITMSG 文件,避免重复并统一格式为 branch-name:(/ 替换为 -),且需校验首行是否已有规范前缀。

Git commit hook 里怎么获取当前分支名
Git 钩子脚本本身不自动暴露分支名,得靠 git symbolic-ref --short HEAD 或 git rev-parse --abbrev-ref HEAD 主动查。前者在分离头(detached HEAD)时会报错,后者更健壮,返回 HEAD 字符串时说明没在任何分支上——这恰恰是你该拦截提交的信号。
实操建议:
- 在
.git/hooks/pre-commit里别直接写逻辑,改用pre-commit脚本调用外部 Python/Shell 脚本,方便测试和维护 - 用
git rev-parse --abbrev-ref HEAD获取分支名,结果为空或等于HEAD时跳过前缀添加,避免误操作 - 注意 Windows 下换行符和权限问题:
pre-commit文件需是 LF 结尾、无 BOM、有执行权限(Linux/macOS 用chmod +x)
如何安全地给 commit message 加前缀而不破坏已有格式
用户可能手动写了带前缀的提交信息,或者用了 git commit -m "feat: xxx" 这类规范格式。硬塞前缀会导致重复,比如 feature/login: feat: xxx。
实操建议:
- 只处理未指定
-m参数的交互式提交:检查git status --porcelain后是否触发编辑器,再读取 .git/COMMIT_EDITMSG 做前置插入 - 用正则判断首行是否已含常见前缀(
^([a-z]+|fix|feat|chore|docs|test):),匹配则跳过 - 前缀格式统一用
branch-name:(不含斜杠),比如login-page:;分支名含/时替换为-,避免被误识别为路径
pre-commit 脚本里怎么读写 COMMIT_EDITMSG
.git/COMMIT_EDITMSG 是 Git 提交给编辑器前生成的临时文件,hook 可以直接修改它,但必须在编辑器打开前完成——所以必须放在 prepare-commit-msg 钩子里,不是 pre-commit。
实操建议:
- 钩子脚本路径必须是
.git/hooks/prepare-commit-msg,且确保可执行 - 用
sed -i '' '1s/^/feature-login: /'(macOS)或sed -i '1s/^/feature-login: /' "$1"(Linux)往第一行开头插入,$1就是 COMMIT_EDITMSG 文件路径 - 加
if [ -z "$(head -n1 "$1" | grep ':')" ]; then ... fi判断首行是否已有冒号,有就跳过
为什么不用 Husky 或其他第三方工具
单纯加分支前缀这事,引入 Husky 等工具反而增加依赖和调试成本:Node.js 版本冲突、Windows 权限异常、钩子未激活等错误比 shell 脚本多得多。
实操建议:
- 纯 Git 钩子足够轻量,
prepare-commit-msg是 Git 原生命令,无需额外运行时 - 如果团队已用 Husky,可在
husky/pre-commit里调用git rev-parse --abbrev-ref HEAD,但注意 Husky 的prepare-commit-msg钩子需手动配置,不是默认启用 - 分支名含特殊字符(如
feature#123)时,shell 脚本要加引号包裹变量,否则#被当注释,前缀变空


















