You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于提交信息前缀自动升级package.json版本并纳入Commit?

解决Commit时基于前缀自动升级package.json版本的问题

让我帮你逐一拆解并解决遇到的核心问题:

1. 读取.git/COMMIT_EDITMSG的方式是否正确?

这个方式在prepare-commit-msg钩子中是完全正确的,但在pre-commit钩子中完全不可行,原因在于Git钩子的触发时机:

  • pre-commit触发时,用户还没输入提交信息(不管是用-m参数还是编辑器),此时.git/COMMIT_EDITMSG要么不存在,要么存的是上一次提交的内容——这就是你在pre-commit里只能拿到旧提交信息的根源。
  • prepare-commit-msg触发时,Git已经生成了当前提交的信息(默认模板或-m传入的内容)并写入该文件,所以此时读取能拿到准确的本次提交信息。

2. pre-commit钩子中能否获取当前待提交的信息?

不能。pre-commit的触发节点是「用户输入提交信息之前、暂存区内容确定之后」,此时Git还没生成任何和当前提交相关的信息文件,没有渠道能拿到本次提交的前缀。因此pre-commit完全不适合实现「基于当前提交前缀升级版本」的需求。

3. prepare-commit-msg钩子中,如何将package.json的版本变更纳入当前Commit?

你的核心思路(执行git add ./package.json)是对的,只是需要补充几个细节确保生效:

关键调整点

  • 检查git add执行结果:shelljs执行命令后要判断返回码,避免命令失败却静默跳过:
    const addResult = shell.exec("git add ./package.json");
    if (addResult.code !== 0) {
      console.error("Failed to stage package.json");
      done(new Error("Git add failed"));
      return;
    }
    
  • 正确解析版本号:你代码里的patch/minor/major变量未定义,需要从package.json中拆分:
    const [major, minor, patch] = pkg.version.split(".").map(Number);
    
  • 确保钩子脚本可执行:.git/hooks/prepare-commit-msg文件需要有执行权限,内容示例:
    #!/bin/sh
    npx gulp bump-version
    
    执行chmod +x .git/hooks/prepare-commit-msg赋予权限即可。

为什么这样能生效?

prepare-commit-msg触发时,Git还处于提交流程的早期阶段:

  • 此时执行git add会把package.json的新版本变更加入暂存区,Git在后续提交步骤中会自动包含所有暂存文件——包括你刚刚添加的版本变更。
  • 不管你是用git commit -m "MJ: fix bug"直接提交,还是打开编辑器输入信息,这个流程都能正常工作。

调整后的完整Gulp任务示例

import * as fs from "fs";
import gulp from "gulp";
import * as shell from "shelljs";
import pkg from "./package.json";

// 定义常量
const MINOR_PREFIX = "^";
const PATCH_PREFIX = "MJ";
const BUMP_VERSION = { task: "bump-version" };
const EC = { NOT_VERSION: 0 };

const getCommitMsg = () => {
  try {
    return fs.readFileSync(".git/COMMIT_EDITMSG", "utf8").trim();
  } catch (err) {
    console.error("Failed to read commit message:", err);
    return "";
  }
};

gulp.task(
  BUMP_VERSION.task,
  (done) => {
    const message = getCommitMsg();
    if (!message) {
      done(new Error("Could not retrieve commit message"));
      return;
    }

    const isMinor = message.startsWith(MINOR_PREFIX);
    const isPatch = message.startsWith(PATCH_PREFIX);

    if (!isMinor && !isPatch) {
      console.log("No version bump prefix detected, skipping");
      done();
      return;
    }

    // 解析当前版本号
    const [major, minor, patch] = pkg.version.split(".").map(Number);
    const newPatch = isPatch ? patch + 1 : patch;
    const newMinor = isMinor ? minor + 1 : minor;
    const newVersion = `${major}.${newMinor}.${newPatch}`;

    // 更新package.json
    const newPkg = { ...pkg, version: newVersion };
    try {
      fs.writeFileSync("./package.json", JSON.stringify(newPkg, null, 4));
      console.log(`Updated version to ${newVersion}`);
    } catch (err) {
      console.error("Failed to write package.json:", err);
      done(err);
      return;
    }

    // 暂存变更
    const addResult = shell.exec("git add ./package.json");
    if (addResult.code !== 0) {
      console.error("Failed to stage package.json");
      done(new Error("Git add failed"));
      return;
    }

    done();
  },
);

总结最佳实践

  • 放弃pre-commit钩子:它无法获取当前提交信息,完全不匹配你的需求。
  • 采用prepare-commit-msg钩子:既能拿到当前提交的前缀,又能通过git add将版本变更纳入本次提交。
  • 给钩子脚本加执行权限,同时在Gulp任务中加入错误处理,避免静默失败。

内容的提问来源于stack exchange,提问作者MaxiJonson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:55:29