git-commit-diy-hook
v1.1.0
Published
Add a fixed timestamp suffix to git commit titles via commit-msg hooks.
Readme
git-commit-diy-hook
Add a fixed timestamp suffix to the Git commit title.
为 Git commit 标题追加一个固定格式的时间后缀。
feat: demo <🐥 2026-05-07 10:11:14>Configuration / 配置
Configure the consuming repository in package.json:
在使用方仓库的 package.json 中配置:
{
"gitCommitDiyHook": {
"allowedEmails": [
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]"
],
"defaultTemplate": " <🐥 ${time}>",
"formatByEmail": {
"[email protected]": " <🚀 ${time}>",
"[email protected]": " <🚀 ${time}>",
"[email protected]": " 【🚀 ${time}】"
}
}
}Config fields / 配置字段
| Field | Type | Default | Description |
| --- | --- | --- | --- |
| allowedEmails | string[] | undefined | If omitted, all users are enabled. If provided, only matching git config user.email values will trigger the hook. / 不配置时表示所有用户都启用;配置后只有匹配 git config user.email 的用户才会生效。 |
| defaultTemplate | string | <🐥 ${time}> | Default suffix template. / 默认后缀模板。 |
| formatByEmail | Record<string, string> | {} | Per-email template override. / 按邮箱覆盖模板。 |
Template rules / 模板规则
${time}is the built-in variable.${time}resolves toYYYY-MM-DD HH:MM:SS.Email matching is case-insensitive and trims surrounding spaces.
Users without a personal template in
formatByEmailfall back todefaultTemplate.${time}是内置变量。${time}会被替换成YYYY-MM-DD HH:MM:SS。邮箱匹配时会忽略大小写并自动去掉首尾空格。
formatByEmail中没有单独模板的用户会回退到defaultTemplate。
Configuration examples / 配置示例
Enable everyone with the default template / 全员启用默认模板
{
"gitCommitDiyHook": {
"defaultTemplate": " <🐥 ${time}>"
}
}Only enable a whitelist / 只对白名单用户启用
{
"gitCommitDiyHook": {
"allowedEmails": ["[email protected]", "[email protected]"]
}
}Different template by email / 不同邮箱使用不同模板
{
"gitCommitDiyHook": {
"allowedEmails": ["[email protected]", "[email protected]"],
"defaultTemplate": " <🐥 ${time}>",
"formatByEmail": {
"[email protected]": " <🚀 ${time}>"
}
}
}This package provides:
- a small CLI for
commit-msghooks - a reusable core API for custom integrations
这个包同时提供:
- 可直接接入
commit-msghook 的 CLI - 可复用的核心 API,方便自定义集成
Table of contents / 目录
- Install / 安装
- Quick start / 快速开始
- Hook integration methods / 各种 Hook 接入方式
- Configuration / 配置
- CLI / 命令行
- API / 编程接口
- Behavior details / 行为说明
- Troubleshooting / 常见问题
Install / 安装
npm install -D git-commit-diy-hookThis package is usually installed as a development dependency in the consuming repository.
通常把它安装为业务仓库里的开发依赖。
Quick start / 快速开始
English
- Install the package in the target repository.
- Add
gitCommitDiyHookconfiguration to that repository'spackage.json. - Wire
git-commit-diy-hook run "$1"into the repository'scommit-msghook. - Commit as usual.
中文
- 在目标仓库中安装本包。
- 在目标仓库的
package.json里添加gitCommitDiyHook配置。 - 把
git-commit-diy-hook run "$1"接到仓库的commit-msghook。 - 正常执行
git commit即可。
Hook integration methods / 各种 Hook 接入方式
The core integration command is always:
核心接入命令始终是:
git-commit-diy-hook run "$1"$1 is the commit message file path passed by Git, usually .git/COMMIT_EDITMSG.
$1 是 Git 传入的提交信息文件路径,通常是 .git/COMMIT_EDITMSG。
1. Plain Git hook managed by this package / 使用本包直接管理原生 Git Hook
Use this when the repository does not already use a hook manager such as Husky or simple-git-hooks.
适用于仓库本身没有使用 Husky、simple-git-hooks 等 hook 管理器的情况。
npx git-commit-diy-hook installWhat this command does:
这个命令会做以下事情:
write a managed
.git/hooks/commit-msgupdate that hook in place if it was previously generated by this package
refuse to overwrite an unmanaged existing
commit-msghook写入一个受管的
.git/hooks/commit-msg如果该 hook 本来就是本包生成的,则原地更新
如果发现已有非本包生成的
commit-msghook,则拒绝覆盖
The generated hook looks like this:
生成出来的 hook 大致如下:
#!/bin/sh
# git-commit-diy-hook managed hook
set -eu
ROOT="$(git rev-parse --show-toplevel)"
LOCAL_BIN="$ROOT/node_modules/.bin/git-commit-diy-hook"
if [ -x "$LOCAL_BIN" ]; then
"$LOCAL_BIN" run "$1"
exit 0
fi
if command -v git-commit-diy-hook >/dev/null 2>&1; then
git-commit-diy-hook run "$1"
exit 0
fi
echo "[git-commit-diy-hook] executable not found. Install dependencies or add the package to PATH." >&2
exit 1
.git/hooks/*files are local Git metadata and are not committed into the repository.
.git/hooks/*属于本地 Git 元数据,不会进入仓库版本管理。
2. simple-git-hooks
If the repository already uses simple-git-hooks, add a commit-msg entry in package.json:
如果仓库已经使用 simple-git-hooks,在 package.json 中添加 commit-msg 配置:
{
"scripts": {
"prepare": "simple-git-hooks"
},
"simple-git-hooks": {
"commit-msg": "git-commit-diy-hook run \"$1\""
}
}Then run dependency installation or the prepare script so the hook is installed:
然后执行依赖安装或手动执行 prepare,让 hook 真正落地:
npm install
# or
npm run prepare3. Husky
If the repository already uses Husky, add a commit-msg hook that delegates to this package.
如果仓库已经使用 Husky,就在 Husky 的 commit-msg 里调用本包。
npx husky add .husky/commit-msg 'git-commit-diy-hook run "$1"'An example .husky/commit-msg file:
示例 .husky/commit-msg 内容:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
git-commit-diy-hook run "$1"4. Merge into an existing custom commit-msg hook / 合并到已有自定义 commit-msg Hook
If your repository already has a custom commit-msg script, do not overwrite it blindly. Add this command into your existing flow:
如果仓库已经有自己的 commit-msg 脚本,不要直接覆盖;把下面这行合并进现有流程即可:
git-commit-diy-hook run "$1"Example:
示例:
#!/bin/sh
set -eu
# your own checks
./scripts/check-commit-message.sh "$1"
# append or replace the timestamp suffix
git-commit-diy-hook run "$1"5. Any other hook manager / 其他 Hook 管理器
Any hook manager can integrate this package as long as it supports the commit-msg lifecycle and can pass the commit message file path.
只要某个 hook 管理器支持 commit-msg 生命周期,并且能把提交信息文件路径传进来,就可以接入本包。
Use the same command:
统一使用同一个命令:
git-commit-diy-hook run "$1"CLI / 命令行
git-commit-diy-hook install
Install a managed native Git commit-msg hook into the current repository.
给当前仓库安装一个受管的原生 Git commit-msg hook。
git-commit-diy-hook installgit-commit-diy-hook run <message-file>
Transform the commit message file in place.
直接修改指定的提交信息文件。
git-commit-diy-hook run .git/COMMIT_EDITMSGThis is the command that hook scripts should call.
这就是各种 hook 脚本最终应该调用的命令。
API / 编程接口
import {
DEFAULT_TIME_TEMPLATE,
formatTimestamp,
resolveGitCommitDiyHookRuntime,
shouldRunForCurrentUser,
transformCommitMessage,
} from 'git-commit-diy-hook';
const timestamp = formatTimestamp(new Date());
if (shouldRunForCurrentUser()) {
const runtime = resolveGitCommitDiyHookRuntime();
const nextMessage = transformCommitMessage(
'feat: demo\n',
timestamp,
runtime.template ?? DEFAULT_TIME_TEMPLATE,
runtime.knownTemplates,
);
}Useful exported functions:
常用导出方法:
formatTimestamp(date?): format a date asYYYY-MM-DD HH:MM:SStransformCommitMessage(message, timestamp, template?, removableTemplates?): add or replace the suffix on the first commit title lineresolveGitCommitDiyHookRuntime(cwd?): read config, current email, active template, and known templatesshouldRunForCurrentUser(cwd?): check whether the current Git user should trigger the hookformatTimestamp(date?):把日期格式化为YYYY-MM-DD HH:MM:SStransformCommitMessage(message, timestamp, template?, removableTemplates?):在标题首行追加或替换后缀resolveGitCommitDiyHookRuntime(cwd?):读取配置、当前邮箱、当前模板和所有已知模板shouldRunForCurrentUser(cwd?):判断当前 Git 用户是否应该触发 hook
Behavior details / 行为说明
Only the first non-empty, non-comment line is modified.
The rest of the commit body is preserved.
Lines starting with
#are preserved.If a known template already exists at the end of the title, it is replaced instead of duplicated.
CRLF line endings are preserved.
只会修改第一行非空、且不是注释的内容。
commit body 其他正文会保留。
以
#开头的注释行会保留。如果标题末尾已经有已知模板生成的时间后缀,会替换而不是重复追加。
会保留 CRLF 换行格式。
Troubleshooting / 常见问题
The commit title is not changing / 提交时没有生效
Check the following:
检查以下几点:
Is the repository actually running a
commit-msghook?If
allowedEmailsis configured, does it matchgit config user.emailexactly?Is the package installed in the repository where you are committing?
Are you using a hook manager such as Husky or
simple-git-hooksbut forgot to wiregit-commit-diy-hook run "$1"?当前仓库是否真的执行了
commit-msghook?如果配置了
allowedEmails,它是否和git config user.email完全匹配?你提交的那个仓库里是否已经安装了本包?
是否使用了 Husky 或
simple-git-hooks,但没有把git-commit-diy-hook run "$1"接进去?
install refuses to overwrite commit-msg / install 拒绝覆盖已有 commit-msg
This means the repository already has an unmanaged commit-msg hook.
这说明仓库里已经有一个不是本包生成的 commit-msg hook。
Recommended handling:
推荐处理方式:
keep the existing hook
manually add
git-commit-diy-hook run "$1"into that script保留原来的 hook
手动把
git-commit-diy-hook run "$1"合并进去
executable not found / 提示找不到可执行文件
The generated native hook first looks for:
原生受管 hook 会按这个顺序查找可执行文件:
node_modules/.bin/git-commit-diy-hook- global
git-commit-diy-hookinPATH
If neither exists, install dependencies in the target repository first.
如果两者都不存在,请先在目标仓库中安装依赖。
Does .git/hooks/commit-msg get committed? / .git/hooks/commit-msg 会提交到仓库吗?
No. .git/hooks/* is local-only.
不会。.git/hooks/* 只存在于本地。
If you want a team-wide setup, prefer Husky or simple-git-hooks, because their configuration is stored in the repository.
如果你想让团队统一接入,优先使用 Husky 或 simple-git-hooks,因为它们的配置是放在仓库里的。
