在现代软件开发中,保持一致的提交信息格式,就像保持好身材一样重要。它不仅让你的代码历史记录井井有条,还能为团队协作和版本控制注入一股神奇的力量!Conventional Commits(传统提交)标准正是为了实现这一目标而诞生的。
今天,我将带你一起搭建一个命令行工具,它不仅能生成符合 Conventional Commits 标准的 Git 提交消息,还能帮你验证提交信息的格式。想象一下,这就像你在用一个强大的自动化助手,让你的每一次提交都规范化、清晰化,工作效率倍增!
📜 目录
🎯 什么是 Conventional Commits?
Conventional Commits 是一种高效规范的 Git 提交信息格式,它能让提交历史清晰易懂,也为自动化版本管理打下了基础。基本格式如下:
<type>(<scope>): <description>
- type:提交类型,如
feat
(新增功能)、fix
(修复问题)等。 - scope:提交的范围(可选),如
login
、button
,指明你修改了哪个模块。 - description:简洁明了的描述,告诉大家你做了哪些变动。
例如:
feat(login): add user authentication
fix(button): resolve button hover issue
这样一来,代码历史变得简洁明了,自动化工具也能轻松地解析提交记录,进行自动化发布和版本控制。是不是很酷?
🛠️ 工具功能概述
下面让我们看看这个神奇的 Conventional Commits 命令行工具能为你做些什么:
- Git 提交生成器:通过交互式命令行收集提交类型、范围和描述,自动生成符合标准的 Git 提交信息。有没有觉得很有趣?
- 提交验证器:在提交之前,工具会帮你检查提交信息格式,确保它符合 Conventional Commits 标准,避免你在提交信息上犯低级错误。
先看效果!👀
⚙️ 实现细节
这个工具是用 Node.js 编写的,依赖了一些非常棒的库:
@clack/prompts
:让我们的命令行界面看起来更加精致。execa
:让我们轻松执行 Git 命令,像魔法一样便捷。chalk
:给终端输出加点颜色,让结果更加吸引眼球。fs
和path
:用来处理文件操作和路径管理,让一切变得更简单。
1. Git 提交生成器 (gitCommit
)
通过交互式命令行,用户可以依次选择:
- 提交类型:比如
feat
(新增功能)、fix
(修复问题)、docs
(文档更新)等。 - 提交范围:比如修改了哪个模块(可选)。
- 提交描述:简洁的描述,说明你做了哪些改动。
然后,工具会自动生成提交信息,并通过 git commit
命令提交。是不是很酷?🤩
2. 提交信息验证器 (gitCommitVerify
)
在你提交之前,工具会自动检查你的提交信息是否符合标准。如果提交信息不符合,它会友好地提醒你。再也不用担心提交信息不规范了!👏
💻 代码实现
接下来,让我们看看这两个功能模块的核心代码实现:
gitCommit
函数:生成 Git 提交信息
export async function gitCommit(lang: Lang = 'en-us') {
const { gitCommitMessages, gitCommitScopes, gitCommitTypes } = locales[lang];
// 选择提交类型
const type = await select({
message: gitCommitMessages.types,
options: gitCommitTypes.map(([value, msg]) => ({
label: `${value.padEnd(12)}: ${msg}`,
value,
})),
});
if (isCancel(type)) {
note(gitCommitMessages.canceled, 'red');
return;
}
// 选择提交范围
const scope = await select({
message: gitCommitMessages.scopes,
options: [
{ label: gitCommitMessages.noScope, value: '' },
...gitCommitScopes.map(([value, msg]) => ({
label: `${value.padEnd(30)}: ${msg}`,
value,
})),
],
});
if (isCancel(scope)) {
note(gitCommitMessages.canceled, 'red');
return;
}
// 输入提交描述
const description = await text({
message: gitCommitMessages.description,
placeholder: 'Enter a brief commit description...',
validate: (value) => {
if (!value) return gitCommitMessages.emptyDescription;
if (value.length > 100) return gitCommitMessages.descriptionTooLong;
return undefined;
},
});
if (isCancel(description)) {
note(gitCommitMessages.canceled, 'red');
return;
}
// 格式化提交信息
const breaking = description.startsWith('!') ? '!' : '';
const finalDescription = description.replace(/^!/, '').trim();
const scopePart = scope ? `(${scope})` : '';
const commitMsg = `${type}${scopePart}${breaking}: ${finalDescription}`;
// 执行 Git 提交
const s = spinner();
s.start(gitCommitMessages.committing);
try {
await execaCommand(`git commit -m "${commitMsg}"`, {
shell: true,
stdio: 'inherit',
});
s.stop();
outro(gitCommitMessages.commitSuccess);
} catch (error) {
s.stop();
note(gitCommitMessages.commitFailed, 'red');
console.error(error);
}
}
gitCommitVerify
函数:验证提交信息
export async function gitCommitVerify(
lang: Lang = 'en-us',
ignores: RegExp[] = [],
) {
const { stdout: gitPath } = await execaCommand('git rev-parse --show-toplevel');
const gitMsgPath = path.join(gitPath, '.git', 'COMMIT_EDITMSG');
const commitMsg = readFileSync(gitMsgPath, 'utf8').trim();
if (ignores.some((regExp) => regExp.test(commitMsg))) return;
const REG_EXP = /[a-z]+(?:(.+))?!?: .+/i;
if (!REG_EXP.test(commitMsg)) {
const errorMsg = locales[lang].gitCommitVerify;
throw new Error(errorMsg);
}
}
🚀 总结
这个命令行工具不仅让你的 Git 提交符合 Conventional Commits 标准,而且提高了团队的协作效率。简洁的交互式界面和自动化验证功能,让每次提交都变得简单、高效、无忧。
如果你还没有尝试过 Conventional Commits,现在是时候加入了!用这个工具来规范你的 Git 提交信息,让代码管理更加井然有序,团队协作更高效!
快来试试吧,让每一次提交都充满意义!🎉