从零开发 Git 提交 AI 神器|全栈实战(React+Express+Ollama)
作为开发者,你是否也遇到过这些问题?提交 Git 时想不出规范的提交信息、手写的信息杂乱无章不便于后续追溯、新手不懂高级提交规范导致项目日志混乱?甚至 leader 审核工作业绩时,因提交信息不清晰无法快速了解你的工作量?
今天就带大家从零开发一款 Git 提交 AI 神器,基于 React+Express+Ollama 全栈技术栈,本地部署开源大模型,自动生成符合 Conventional Commits 规范的提交信息,让新手也能像高手一样规范提交代码,同时解决项目日志追溯、业绩审核的痛点。
全程实战无废话,从需求分析、技术选型到核心代码解析、避坑指南,一步步带你落地,看完就能直接上手部署使用!
一、需求分析:为什么需要这款 Git 提交 AI 神器?
一款实用的工具,必先解决实际痛点。我们这款 Git 提交 AI 神器,核心需求围绕「规范 Git 提交信息」展开,具体拆解为 3 点:
- 规范项目日志:统一的提交信息格式,让项目迭代记录清晰可追溯,后续排查问题、回滚版本时能快速定位关键变更;
- 助力业绩审核:清晰、规范的提交信息(如 feat、fix、refactor 等类型),能让 leader 快速了解你的开发工作量和成果;
- 降低新手门槛:新手无需死记硬背 Git 高级提交规范,通过 AI 自动生成,就能写出符合行业标准的提交信息,快速融入团队开发。
二、技术选型:全栈架构+本地 AI 部署
考虑到工具的实用性、易用性和隐私性(无需调用第三方 AI 接口,避免代码变更信息泄露),我们采用「前后端分离+本地大模型部署」的架构,具体技术栈如下:
1. 整体架构:前后端分离
采用经典的前后端分离模式,前端负责交互展示,后端提供 API 服务,AI 层负责核心的提交信息生成,三者独立部署、协同工作:
- 前端(Frontend) :运行在用户浏览器(V8 引擎宿主),端口 5173,负责接收用户输入、展示 AI 生成的提交信息;
- 后端(Server) :运行在服务器,端口 3000,提供 API 接口,处理前端请求、调用 AI 模型;
- AI 层:通过 Ollama 部署开源大模型 deepseek-r1:8b(支持 GPU 推理),提供类 OpenAI 的 API 接口,端口 11434,负责生成规范的 Git 提交信息。
2. 技术栈细节
- 前端:React(UI 框架)+ TailwindCSS(原子化样式,快速开发)+ Axios(HTTP 请求库,封装接口调用);
- 后端:Node.js + Express(老牌敏捷开发框架,快速搭建 API 服务);
- AI 集成:LangChain(大模型应用开发框架,简化 Ollama 调用)+ Ollama + deepseek-r1:8b(开源大模型,本地部署,隐私安全);
- 开发/测试工具:Nodemon(后端热更新,边调试边开发)+ Apifox(API 接口测试)。
三、核心开发实战:从 0 到 1 搭建服务
下面我们分「后端服务」「前端页面」「AI 集成」三个部分,拆解核心代码,每一步都有详细注释,新手也能轻松跟上。
1. 后端开发:Express 服务搭建(核心)
后端的核心作用是提供 API 接口,处理前端请求,调用本地 Ollama 模型,返回 AI 生成的提交信息。首先初始化项目并安装依赖,然后编写核心代码。
1.1 初始化后端项目
# 创建后端目录
mkdir -p git-commit-ai/server && cd git-commit-ai/server
# 初始化 package.json
npm init -y
# 安装依赖
npm install express cors @langchain/ollama @langchain/core
npm install nodemon --save-dev
1.2 核心代码(server/index.js)
代码包含 Express 服务初始化、跨域配置、JSON 解析中间件、核心 API 接口(/hello 测试接口、/chat AI 调用接口),关键部分都有详细注释:
// 引入后端依赖
import express from 'express'; // 引入Express框架
import cors from 'cors'; // 引入跨域模块,解决前后端跨域问题
// LangChain相关依赖,用于简化Ollama大模型调用
import { ChatOllama } from '@langchain/ollama';
import { ChatPromptTemplate } from '@langchain/core/prompts'; // 提示词模板
import { StringOutputParser } from '@langchain/core/output_parsers'; // 输出格式化
// 初始化Ollama大模型实例(本地部署的deepseek-r1:8b)
const model = new ChatOllama({
baseUrl: "http://localhost:11434", // Ollama服务默认地址
model: "deepseek-r1:8b", // 要调用的开源大模型
temperature: 0.1 // 温度系数,0.1表示生成结果更严格、固定(适合规范提交信息)
})
// 创建Express应用实例
const app = express();
// 中间件配置(后端稳定运行的关键)
app.use(express.json()); // 解析JSON格式请求体(POST请求必须加,否则req.body为undefined)
app.use(cors()); // 开启跨域允许,相当于给前端请求"办签证",避免浏览器拦截
// 测试接口:用于验证后端服务是否正常启动
app.get('/hello', (req, res) => {
res.send('hello world'); // 向前端返回纯文本响应
})
// 核心接口:接收前端请求,调用AI生成Git提交信息
app.post('/chat', async (req, res) => {
console.log(req.body, '/////') // 调试日志,查看前端传入的参数
const { message } = req.body; // 从请求体中解构用户输入(如代码变更描述)
// 参数校验(后端稳定第一,避免无效请求)
if (!message || typeof message !== 'string') {
// 400状态码:请求参数错误,返回JSON格式错误提示
return res.status(400).json({
error: "message 必填,必须是字符串"
})
}
try {
// 1. 构建结构化提示词模板(大模型交互的关键)
const prompt = ChatPromptTemplate.fromMessages([
// system角色:定义大模型人设(Git提交信息生成专家)
['system', '你是Git提交信息生成专家,必须遵循Conventional Commits规范。格式要求:<type>(<scope>): <subject>,type可选值:feat(新功能)、fix(修复)、docs(文档)、style(格式)、refactor(重构)、test(测试)、chore(构建),scope为修改的模块,subject简洁明了(不超过50字符),仅返回提交信息,不额外解释。'],
['human', '{input}'] // human角色:用户输入,{input}是占位符,后续替换为message
]);
// 2. 搭建LangChain调用链(流水线式处理:提示词→模型→结果解析)
const chain = prompt
.pipe(model) // 第一步:将格式化的提示词传给大模型
.pipe(new StringOutputParser()); // 第二步:将大模型返回的复杂响应解析为纯字符串
console.log('正在调用大模型');
// 3. 异步调用大模型,传入用户输入,获取AI生成结果
const result = await chain.invoke({
input: message // input键名必须和提示词模板中的{input}占位符一致
})
// 4. 向前端返回AI生成的提交信息(JSON格式,200状态码默认成功)
res.json({
reply: result
})
} catch(e) {
// 异常捕获:处理大模型调用失败、网络错误等问题
console.log(e);
res.status(500).json({
error: "调用大模型失败"
})
}
})
// 启动后端服务,监听3000端口
app.listen(3000, () => {
console.log('server is running on port 3000');
})
1.3 关键知识点补充(避坑重点)
- Express 中间件:
express.json()必须加,否则无法解析 POST 请求的 JSON 体,req.body会是 undefined;cors()必须加,否则前端 5173 端口请求后端 3000 端口会被浏览器同源策略拦截。 - HTTP 状态码规范:400(请求参数错误)、500(服务器内部错误)、200(成功,默认),规范使用状态码,方便前端排查问题。
- Ollama 依赖:必须先启动 Ollama 服务(
ollama serve),且已拉取 deepseek-r1:8b 模型(ollama pull deepseek-r1:8b),否则会报“调用大模型失败”。
2. 前端开发:React 页面+接口封装
前端核心功能:展示加载状态、调用后端 API、展示 AI 生成的 Git 提交信息,采用 React Hooks 封装业务逻辑,实现 UI 与业务分离。
2.1 初始化前端项目
# 回到项目根目录,创建前端项目(Vite+React)
cd ..
npm create vite@latest frontend -- --template react
# 进入前端目录,安装依赖
cd frontend
npm install
npm install axios tailwindcss postcss autoprefixer
npx tailwindcss init -p
2.2 核心代码拆解
前端代码分为 3 部分:Axios 接口封装、React Hooks 业务封装、App 组件 UI 展示,各司其职,便于维护。
(1)接口封装(src/api/index.js)
统一管理 API 请求,避免重复代码,后续扩展接口更方便:
// 导入Axios请求库(比fetch更易用,支持拦截器、超时设置等)
import axios from 'axios';
// 创建Axios实例,配置基础路径、请求头、超时时间
const service = axios.create({
baseURL: 'http://localhost:3000', // 后端服务地址
headers: {
'Content-Type': 'application/json', // 请求体格式为JSON
},
timeout: 60000, // 超时时间60秒,避免大模型调用超时导致请求失败
});
// 封装/chat接口:接收用户输入,调用后端AI接口
export const chat = (message) =>
service.post('/chat', {message}) // POST请求,传入message参数
(2)Hooks 业务封装(src/hooks/useGitDiff.js)
用自定义 Hooks 封装业务逻辑(加载状态、AI 调用、结果存储),实现 UI 组件与业务逻辑分离,符合 React 组件单一职责原则:
import { useState, useEffect } from 'react';
import { chat } from '../api/index.js'; // 导入封装好的接口
// 自定义Hooks:use开头,封装Git提交信息生成的业务逻辑
export const useGitDiff = () => {
const [content, setContent] = useState(''); // 存储AI生成的提交信息
const [loading, setLoading] = useState(false); // 加载状态(控制加载提示)
// 副作用钩子:组件挂载时自动调用AI接口(可后续修改为用户输入后触发)
useEffect(() => {
// 异步函数:调用AI接口
(async () => {
setLoading(true); // 开始加载,显示加载提示
const { data } = await chat('新增用户登录页面的验证码功能'); // 模拟用户输入(后续可改为用户手动输入)
setContent(data.reply); // 将AI返回的结果存入state
setLoading(false); // 加载完成,隐藏加载提示
})()
}, []) // 空依赖数组:组件只挂载时执行一次
// 返回状态和数据,供UI组件使用
return {
loading, // 加载状态
content, // AI生成的Git提交信息
}
}
(3)App 组件(src/App.jsx)
UI 展示组件,简洁明了,根据加载状态显示不同内容:
import { useEffect } from 'react';
import { useGitDiff } from './hooks/useGitDiff.js';
export default function App() {
// 调用自定义Hooks,获取加载状态和AI生成的提交信息
const { loading, content } = useGitDiff();
return (
{/* 加载状态显示loading,加载完成显示AI生成的提交信息 */}
{loading ? 'loading.....' : (
AI生成的Git提交信息:{content}
)}
)
}
2.3 TailwindCSS 配置(可选)
确保 TailwindCSS 正常生效,修改 tailwind.config.js:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}", // 扫描所有React组件,按需生成CSS
],
theme: {
extend: {},
},
plugins: [],
}
在 src/index.css 中引入 Tailwind 指令:
@tailwind base;
@tailwind components;
@tailwind utilities;
3. AI 层部署:Ollama + deepseek-r1:8b
这是工具的核心,本地部署大模型,无需调用第三方 API,隐私安全且无网络依赖,步骤如下:
- 安装 Ollama:前往 Ollama 官网,下载对应系统版本(Windows/Mac/Linux),一键安装;
- 拉取模型:打开终端,执行
ollama pull deepseek-r1:8b,等待模型下载完成(需联网,大小约 4GB,GPU 加速可提升下载和推理速度); - 启动 Ollama 服务:执行
ollama serve,默认监听 11434 端口,与后端代码中配置的baseUrl: "http://localhost:11434"保持一致。
四、项目启动与测试
所有代码编写完成后,按以下顺序启动项目,即可测试功能:
1. 启动 Ollama 服务
ollama serve
2. 启动后端服务
cd server
npm run dev # 借助nodemon实现热更新
终端显示 server is running on port 3000,说明后端服务启动成功。
3. 启动前端服务
cd ../frontend
npm run dev
终端显示 http://localhost:5173/,打开浏览器访问该地址,即可看到 AI 生成的 Git 提交信息。
4. 接口测试(Apifox)
打开 Apifox,创建 POST 请求,地址 http://localhost:3000/chat,请求体 JSON 格式:{"message": "新增用户登录功能"},发送请求,即可收到 AI 返回的规范提交信息(如 feat(login): 新增用户登录功能)。
五、常见问题与避坑指南
开发过程中,新手容易遇到以下问题,提前规避,提高开发效率:
1. 后端启动报错:nodemon: command not found
原因:nodemon 未全局安装,解决方案:
npm install -g nodemon
2. 后端报错:Cannot find package 'cors'
原因:依赖未安装或安装路径错误,解决方案:
cd server
rm -rf node_modules package-lock.json
npm install --registry=https://registry.npm.taobao.org
3. 前端跨域报错:Access to XMLHttpRequest at ...
原因:后端未开启跨域,解决方案:确保后端代码中添加 app.use(cors()),且放在路由之前。
4. AI 调用失败:调用大模型失败
原因:Ollama 服务未启动,或模型未拉取,解决方案:
- 启动 Ollama 服务:
ollama serve; - 拉取模型:
ollama pull deepseek-r1:8b; - 检查后端代码中
baseUrl是否为http://localhost:11434。
六、功能扩展方向(可选)
当前版本已实现核心功能,后续可根据需求扩展,让工具更实用:
- 添加用户输入框:允许用户手动输入代码变更描述,生成个性化提交信息;
- 支持提交类型选择:让用户手动选择 feat/fix/docs 等类型,进一步规范提交信息;
- 流式返回:实现 AI 回复逐字显示的“打字机效果”,提升用户体验;
- 集成 Git 命令:直接在工具中执行
git commit -m "AI生成的信息",无需手动复制粘贴。
七、总结
本文从零开发了一款 Git 提交 AI 神器,基于 React+Express+Ollama 全栈技术栈,实现了“前端交互→后端处理→AI 生成→结果展示”的完整流程,解决了 Git 提交信息不规范的痛点。
整个项目难度适中,适合前端/全栈新手实战,既能巩固 React、Express 的基础用法,又能接触到 LangChain、本地大模型部署等热门技术,提升自身竞争力。
后续可以根据自己的需求扩展功能,也可以将工具封装成 CLI 命令,集成到自己的开发流程中,提高开发效率。