把 git commit 这件事,彻底交给 AI ——一个工程化 /git-commit 命令的设计与落地

系列:AI 工程化实践(核心 1/5)------ 基础设施篇

写在系列开头:我做这套东西的真实起点

这个系列核心 5 篇 + 3 篇延伸------核心讲我做的 4-skill + 熵管理全闭环;延伸讲相邻项目的设计哲学、个人成长故事和可量化原则。这一篇是核心系列的第 1 篇,会从 4 个 skill 自闭环讲到熵管理方法论的源头------所有这些产出都源自一个非常具体的工作场景

我刚进腾讯团队那段时间,周一到周五经常干到晚上 11-12 点 ------业务 feature 加 bug 单推着走。但大概 2 周后我意识到这样不可持续 ------不是身体扛不住,是我根本没时间做自己想做的有杠杆的事,每天都在做"机械工作量",能力一点都不增长。

所以我做了一个决定------主动找 mentor 谈,转向做 skill 提效

我管这个决策叫 "提效优先级原则"

忙不过来的时候,先想哪些重复步骤可以写 skill 提效,而不是硬撑着把活做完。

等效率上去了,才有空闲时间去做真正硬的活------比如性能优化、架构升级。

听起来很普通对吧?但 99% 的工程师在压力下的本能反应是反的------忙了就加班,活多了就硬刚,结果是越干越累,越累越没时间优化,最终被淹没。

这篇文章是这个原则落地的第一个产物 ------/git-commit skill。它解决的是"每次 commit 占 3 分钟"这件最普通、但每天发生 10+ 次的事。

做完这个 skill 之后,我每天解锁 30 分钟可支配时间 ------这点时间看起来不多,但它是后面整个 4-skill 自闭环 + 熵管理方法论生长出来的种子


背景:你每天在 commit 上浪费了多少时间?

如果你在一个多包仓库里干活,每次提交大概会经历这几步:

  1. 切到对应的子仓库目录
  2. git status / git diff 看改了啥
  3. 想一个符合团队规范的 commit message
  4. 加上 story / bug ID 前缀( story 代表需求)
  5. 决定推到 main 还是某个 stable 分支
  6. 如果是 stable 分支,要单独建 hotfix 分支、提 MR、等 review
  7. 最后回 Tapd 把单子状态改一下

我做过粗略的估计:在一个 monorepo 项目里,单次提交平均 3~5 分钟 ,一周 20+ 次 commit,纯仪式性时间 2 小时

更糟糕的是这套流程几乎全是"机械记忆" ------一旦记错(比如 stable 分支错走了 main,或者忘了加 --bug= 前缀),CI 直接打回,又是 10 分钟。

我的判断:任何"纯流程性、无创造性、规则明确"的工作,都应该从人手里拿走。

这篇文章讲的就是我怎么把这套流程压成一个 /git-commit 命令,让 Cursor 一键搞定。


一、目标:3 个核心约束

在动手设计之前,我先把目标拆清楚:

约束 1:单一入口,零认知负担

用户只需要输入 /git-commit,剩下的全靠 AI 主动问。

约束 2:多分支路由必须 100% 正确

我们仓库的分支策略是:

分支类型 处理方式
main / dev / 自定义 Path B:直接 commit + push
stableYYYYMMDD(如 stable20260409 Path A:从 stable 拉 hotfix 分支 → 提 MR
releaseYYYYMMDD 委托给 git-bugfix skill(branch-policy-v1)

走错一次,CI 报错,整个流水线回滚------容错率 = 0

约束 3:Tapd 状态自动流转

提交完代码不是结束。Bug 单要变 已解决、Story 要变 开发完成待验收,否则测试同学没法接手。人手动改,有概率会忘


二、整体架构

整个 skill 的执行流程是这样的:

vbnet 复制代码
用户输入 /git-commit
       ↓
Step 1: AskQuestion 收集信息(包名 + 类型 + ID + 目标分支多选)
       ↓
Step 2: Validate(stable 分支只接受 bug 修复等约束)
       ↓
Step 3: 展示 diff + 用户确认要 stage 的文件
       ↓
Step 4: 分支路由
        ├─ main / dev → Path B:直接 commit + push
        ├─ stable*    → Path A:拉 hotfix 分支 + push + 创建 MR
        └─ release*   → 委托给 git-bugfix skill
       ↓
Step 5: TAPD 状态流转(bug → 已解决 / story → 开发完成待验收)
       ↓
最终:输出 summary 表格

下面挑几个真正难的部分展开。


三、关键设计 1:用 AskQuestion 实现"结构化对话"

最早我让 AI 自己读对话上下文 来推断"用户要往哪个分支提"------结果非常不稳定:用户说"提到 main 和 stable",AI 可能漏掉一个、可能解析出 stable 但没跟具体日期,也曾对此进行了一些简单的测试,错误率超过 30%。

后来改成 强制结构化提问

json 复制代码
{
  "title": "Git commit --- target branch(es)",
  "questions": [
    {
      "id": "target_branches",
      "prompt": "目标分支(可多选):选 main 则直接 push;选 stableYYYYMMDD 则走 hotfix + MR。",
      "options": [
        { "id": "main", "label": "main --- 直接 commit + push(Path B)" },
        { "id": "stable20260409", "label": "stable20260409 --- hotfix + MR(Path A)" },
        { "id": "stable20260325", "label": "stable20260325 --- hotfix + MR(Path A)" },
        { "id": "other", "label": "其他分支(在聊天里写明分支名)" }
      ],
      "allow_multiple": true
    }
  ]
}

关键点:

  • allow_multiple: true :支持同时推到 main 和多个 stable,这是真实业务里最常见的诉求(修个 bug 既要进主干又要进当前发布分支)
  • stable 选项动态生成 :用 git branch -r 拉最近 5 条严格匹配 ^stable[0-9]{8}$ 的分支,避免老分支污染选项
  • labels 里直接写明"会做什么"Path A / Path B 让用户对副作用有预期

经验:让 AI 推断 vs 让用户结构化选,在工程化场景永远选后者。LLM 的不确定性是工具链的灾难。


四、关键设计 2:双路径执行 + cherry-pick 兜底

最有意思的设计是 当用户同时勾选 mainstable 时怎么办

错误的做法

最初我让 AI 在每个分支上独立 commit:

bash 复制代码
# 错误版本:分别在 main 和 stable 上做 stash + commit
git checkout main && git stash pop && git add ... && git commit ...
git checkout stable20260409 && git stash pop && git add ... && git commit ...

第一周就翻车 :因为 stash pop 在第二次操作时已经空了。

正确的做法:先做主干,再 cherry-pick

markdown 复制代码
1. fetch origin
2. 先在 main 上完成 Path B(stage → commit → push)
   → 记录 COMMIT_SHA = $(git rev-parse HEAD)
3. 对每个 stable 分支:
   - 从 origin/<stable> 拉 hotfix 分支
   - git cherry-pick $COMMIT_SHA   ← 关键
   - push + 创建 MR

为什么 cherry-pick 是对的?

  • ✅ commit 内容完全一致(同一个 SHA 派生)
  • ✅ 工作区不需要 stash 来回腾挪
  • ✅ 冲突时 git 能直接报告,不会静默吞掉

多个 stable 分支的命名也要细心

bash 复制代码
fix/bug-133058995-stable20260409
fix/bug-133058995-stable20260325

加上 stable 后缀,避免远端已存在分支冲突。


五、关键设计 3:Commit Message 自动生成

这一块是 LLM 真正能发挥的地方。

我给 AI 的 prompt 是:

  1. 读取 git diff --cached 的 staged 内容
  2. 分析改动的本质(功能 / 修复 / 重构 / 文档 / 配置)
  3. 生成简洁的英文描述(<= 72 字符)
  4. 套用 Conventional Commits 格式 + 团队约定的 ID 前缀

输出形如:

sql 复制代码
--story=133058995 feat: add template selector component
--bug=133058995 fix: resolve websocket reconnection timeout
--story=133058995 refactor: extract shared validation logic
chore: update eslint config and add prettier rules

避坑点

  1. type 必须从 diff 推 ,不能让用户选------我试过让用户选 feat / fix / refactor,结果很多同事的 story 都被勾成 feat,但实际上很多是 refactorLLM 看 diff 比人看 diff 更客观
  2. --story= / --bug= 必须放在第 1 行第 1 个位置,团队的 CI 校验是 prefix-based 的,错位置直接 reject。
  3. 多行 commit message 只在第 1 行带前缀
vbnet 复制代码
--bug=133058995 fix: prevent duplicate event listeners on reconnect

Remove stale listeners before registering new ones in the WebSocket
manager to avoid exponential handler accumulation.

六、关键设计 4:MR 自动创建 + reviewer 指派

stable 分支必走 MR 流程。这一段是纯 API 编排:

bash 复制代码
# 1. 解析 remote 拿到 host 和 project_path
REMOTE_URL=$(git remote get-url origin)
# git@git.tencent.com:aw/marketplace.git → HOST=git.tencent.com, PROJECT_PATH=aw/marketplace

# 2. 查 project ID
PROJECT_ID=$(curl -s -H "PRIVATE-TOKEN: $TOKEN" \
  "https://git.tencent.com/api/v3/projects?search=$PROJECT_NAME" | \
  jq -r --arg path "$PROJECT_PATH" '.[] | select(.path_with_namespace == $path) | .id')

# 3. 创建 MR
curl -s -H "PRIVATE-TOKEN: $TOKEN" \
  -X POST -d '{
    "source_branch": "fix/bug-133058995",
    "target_branch": "stable20260409",
    "title": "--bug=133058995 fix: ...",
    "remove_source_branch": true
  }' \
  "https://git.tencent.com/api/v3/projects/$PROJECT_ID/merge_requests"

# 4. 自动添加固定 reviewer
REVIEWER_ID=$(curl -s -H "PRIVATE-TOKEN: $TOKEN" \
  "https://git.tencent.com/api/v3/users?username=simonsliu" | jq -r '.[0].id')

curl -s -H "PRIVATE-TOKEN: $TOKEN" \
  -X PUT -d "{\"reviewer_ids\": [$REVIEWER_ID]}" \
  "https://git.tencent.com/api/v3/projects/$PROJECT_ID/merge_requests/$MR_ID"

踩过的坑

  • 内网走 git.tencent.com,走 git.woa.com 的某些仓库 API v3 不支持自动创建 MR,要降级成"打印手动创建 URL"。否则脚本会卡死在 401。
  • token 放在 ~/.tokens/git.tencent.com/token,避免每次都 prompt 用户输入。
  • reviewer 的 username 不是 ID,要先查一次 /users?username=xxx 拿到 ID。

七、关键设计 5:Tapd 状态流转(best-effort)

提交代码后还有一个"软依赖":把 Tapd 单子的状态改掉。

bash 复制代码
# Bug → 已解决
curl -s -u "$TAPD_AUTH" -X POST \
  -d "id=${TAPD_BUG_ID}&workspace_id=${TAPD_WS}&status=resolved" \
  "${TAPD_API}/bugs"

# Story → 开发完成待验收
curl -s -u "$TAPD_AUTH" -X POST \
  -d "id=${TAPD_STORY_ID}&workspace_id=${TAPD_WS}&v_status=开发完成待验收" \
  "${TAPD_API}/stories"

关键的工程取舍:TAPD 是 best-effort,不能挂 git 流程

我设计的优先级是:

perl 复制代码
git commit & push      ← 主干,必须成功
   ↓
MR 创建                ← 主干,失败时降级到手动 URL
   ↓
TAPD 状态流转          ← 旁支,失败只 print warning,绝不阻塞

理由:网络抖动、TAPD API 偶尔挂、credentials 过期......这些都不应该让用户的代码白提交一次

实现上:

bash 复制代码
if [ -n "$TAPD_CLIENT_ID" ] && [ -n "$TAPD_CLIENT_SECRET" ]; then
  TAPD_AUTH="$TAPD_CLIENT_ID:$TAPD_CLIENT_SECRET"
elif [ -f ~/.tokens/tapd/credentials ]; then
  TAPD_AUTH=$(cat ~/.tokens/tapd/credentials)
else
  echo "⚠️ TAPD credentials not found. Skipping."
  # 不抛错,不退出,继续主流程
fi

工程经验 :辅助系统出错 → 警告 + 降级;核心系统出错 → 中止 + 报错。永远不要让辅助挂掉主干


八、最终效果:从 3 分钟到 30 秒

接入后我自己 1 个月的统计:

指标 接入前 接入后
单次 commit 时间 3~5 分钟 30 秒
走错分支被 CI 打回 周均 2 次 0 次
TAPD 状态遗忘 20%左右 0%
commit message 风格一致度 60% 100%

更重要的是 认知负担变成 0 :我现在写完代码,敲一句 /git-commit,盯着屏幕回 3 个问题,剩下的全自动跑完。


九、方法论升华:什么样的工作适合"AI 化"

写这个 skill 的过程中,我提炼了一套判断标准------不是所有工作都适合交给 AI

维度 适合 AI 接管 不适合
流程明确度 步骤、分支、规则全部可枚举 需要主观判断
副作用 可回滚 / 可幂等 不可逆操作(删数据)
错误成本 错了能立刻发现 错了几个月后才暴露
频率 每天 / 每周高频 一年一次

git-commit 在这 4 个维度上 全部命中

  • ✅ 流程:分支策略 + commit 格式 + Tapd 流转,完全可枚举
  • ✅ 副作用:每一步都能 git reset 或撤回 MR
  • ✅ 错误成本:CI 当场报错,5 分钟修复
  • ✅ 频率:日均 4~6 次

这就是为什么这个 skill 是我在 AI 工程化路上的"第一个杀手锏"------它把一件高频、机械、容错为零的事,从我手上彻底拿走了。


下一篇预告

/git-commit 解决的是 "我已经知道要修什么 → 把代码送出去" 的问题。

但更前面的链路是:Bug 现场 → 我怎么知道要修什么? 这就需要:

  1. 把 Bug 现场(DOM / 日志 / 操作链路)结构化抓下来
  2. 让 AI 自己读 Tapd / 蓝盾日志,定位问题位置

整个系列在试图回答一个问题:

当 AI 已经能写代码,工程师还能为团队增加什么价值?

我的答案是:让 AI 写代码这件事本身,变成一件"工程化"的事------可观测、可重放、可验证、可治理。


如果这篇对你有帮助,欢迎关注,后续几篇会陆续放出。也欢迎在评论区聊聊你团队里"最值得 AI 化"的流程是什么。

相关推荐
触底反弹1 小时前
🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚!
人工智能·设计模式·面试
杨充1 天前
10.可测试性实战设计
设计模式·开源·代码规范
杨充1 天前
9.重构十二式的实战
设计模式·开源·代码规范
杨充1 天前
6.设计原则的全景图
设计模式·开源·全栈
杨充1 天前
2.面向对象的特性
设计模式
杨充1 天前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充1 天前
8.反模式与坏味道
设计模式·开源·代码规范
杨充1 天前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法