Git 提交不再杂乱!🚀 轻松实现 Conventional Commits 标准 ✅

1,499 阅读4分钟

在现代软件开发中,保持一致的提交信息格式,就像保持好身材一样重要。它不仅让你的代码历史记录井井有条,还能为团队协作和版本控制注入一股神奇的力量!Conventional Commits(传统提交)标准正是为了实现这一目标而诞生的。

今天,我将带你一起搭建一个命令行工具,它不仅能生成符合 Conventional Commits 标准的 Git 提交消息,还能帮你验证提交信息的格式。想象一下,这就像你在用一个强大的自动化助手,让你的每一次提交都规范化、清晰化,工作效率倍增!


📜 目录


🎯 什么是 Conventional Commits

Conventional Commits 是一种高效规范的 Git 提交信息格式,它能让提交历史清晰易懂,也为自动化版本管理打下了基础。基本格式如下:


<type>(<scope>): <description>

  • type:提交类型,如 feat(新增功能)、fix(修复问题)等。
  • scope:提交的范围(可选),如 loginbutton,指明你修改了哪个模块。
  • description:简洁明了的描述,告诉大家你做了哪些变动。

例如:


feat(login): add user authentication 
fix(button): resolve button hover issue

这样一来,代码历史变得简洁明了,自动化工具也能轻松地解析提交记录,进行自动化发布和版本控制。是不是很酷?


🛠️ 工具功能概述

下面让我们看看这个神奇的 Conventional Commits 命令行工具能为你做些什么:

  1. Git 提交生成器:通过交互式命令行收集提交类型、范围和描述,自动生成符合标准的 Git 提交信息。有没有觉得很有趣?
  2. 提交验证器:在提交之前,工具会帮你检查提交信息格式,确保它符合 Conventional Commits 标准,避免你在提交信息上犯低级错误。

先看效果!👀

image.png image.png

⚙️ 实现细节

这个工具是用 Node.js 编写的,依赖了一些非常棒的库:

  • @clack/prompts:让我们的命令行界面看起来更加精致。
  • execa:让我们轻松执行 Git 命令,像魔法一样便捷。
  • chalk:给终端输出加点颜色,让结果更加吸引眼球。
  • fspath:用来处理文件操作和路径管理,让一切变得更简单。

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 提交信息,让代码管理更加井然有序,团队协作更高效!

快来试试吧,让每一次提交都充满意义!🎉

完整代码地址