💡 为什么需要规范化 Git 提交信息?
规范的 Git 提交信息是软件开发中的重中之重,它不仅仅是一串文字,更是项目的"活文档"。从项目管理的角度来看,规范的提交日志可以帮助团队:
- 清晰记录项目演进:每一次提交都有明确的说明,让后人能快速理解代码变更的历史背景
- 便于工作业绩审核:leader 可以通过提交日志清晰了解团队成员的工作成果
- 降低新手门槛:即使是刚接触团队的新人,也能按照规范提交高质量的代码
- 自动化生成变更日志:基于规范的提交信息,可以自动生成 CHANGELOG.md 文档
可以说,规范的 Git 提交信息是专业开发者的标配。
🛠️ 技术构成:全栈项目架构
这个项目采用了现代化的前后端分离架构,技术栈非常清晰:
前端技术栈:
- React 19.2.0:目前最新的 React 版本,提供了更强大的功能和更好的性能
- TailwindCSS 4.1.18:原子化 CSS 框架,让样式编写变得极其高效
- Axios 1.13.2:强大的 HTTP 请求库,比原生的 fetch 更易用
后端技术栈:
- Node.js:后端运行环境
- Express 5.2.1:Node.js 老牌的敏捷开发框架
- Nodemon:开发工具,支持热重载,边调试边开发
- LangChain:大模型应用开发框架
- DeepSeek-R1:8b:开源推理大模型
AI 技术:
- Ollama:本地部署开源大模型的工具
- 提供类似 OpenAI 的 API 接口,运行在 http://localhost:11434
🏗️ 前后端分离架构详解
🖥️ 后端服务(Server)
后端服务运行在服务器上,主要职责是提供 API 接口,监听 3000 端口。
后端初始化步骤:
npm init -y
pnpm i express
nodemon index.js
安装 AI 相关依赖:
pnpm i langchain @langchain/ollama @langchain/core
pnpm i cors
配置 package.json:
{
"type": "module"
}
添加 "type": "module" 后,Node.js 就支持 ES Modules 语法了,可以使用 import 和 export。
Ollama 大模型部署:
ollama list
ollama pull deepseek-r1:8b
ollama run deepseek-r1:8b
DeepSeek-R1 是一个强大的推理模型,8b 参数版本在普通 GPU 上就能流畅运行。
🎨 前端应用(Frontend)
前端应用在用户的浏览器上运行,利用 V8 引擎执行 JavaScript,通过 http://localhost:5173 访问。
前端初始化步骤:
npm init vite
# 项目名:tailwindcss-demo
# 框架:react
# 语言:javascript
pnpm install tailwindcss @tailwindcss/vite
pnpm i axios
配置 Vite:
vite.config.js 文件需要引入 TailwindCSS 插件:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
react(),
tailwindcss()
],
})
配置全局样式:
在 index.css 中引入 TailwindCSS:
@import "tailwindcss";
🚂 Express 框架深度解析
Express 是 Node.js 生态中最老牌、最稳定的敏捷开发框架,它的设计理念简洁而强大。
Express 核心概念
1. 应用实例(App)
import express from 'express';
const app = express();
app 就是我们的后端应用实例,所有的路由、中间件都挂载在它上面。
2. 监听端口
app.listen(3000, () => {
console.log('server is running on port 3000');
})
listen(3000) 让应用在 3000 端口上监听 HTTP 请求。
HTTP 协议基础
网站的本质是提供资源和服务,HTTP 是基于请求-响应模式的简单协议:
app.get('/hello', (req, res) => {
res.send('hello world');
})
访问 http://localhost:3000/hello 就会收到 "hello world" 的响应。
让我们拆解一下这个 URL:
- IP:找到服务器
- 端口:3000 对应 Express 应用
- 路径(Path):
/hello指定具体的资源 - 方法(Method):GET 表示获取资源,属于 CRUD 操作
请求和响应对象
- req(Request):请求对象,包含客户端发来的所有信息
- res(Response):响应对象,用于向客户端发送响应
中间件(Middleware)
中间件是 Express 的核心概念之一,它就像一个管道,请求会依次经过各个中间件处理:
请求 → 中间件1 → 中间件2 → ... → 路由处理 → 响应
Express 默认不支持解析 req.body,所以需要添加 JSON 解析中间件:
app.use(express.json()); // 解析请求体的 JSON 数据
GET 和 POST 的区别
- GET:没有请求体,参数通常放在 URL 中,用于获取资源
- POST:有请求体,可以发送大量数据,用于创建或提交资源
HTTP 状态码
状态码是响应头的重要组成部分,它告诉客户端请求的处理结果:
- 1XX:请求进行中
- 200 OK:成功
- 201 Created:成功创建资源
- 3XX:重定向
- 400 Bad Request:客户端请求错误
- 404 Not Found:资源不存在
- 401 Unauthorized:未授权
- 500 Internal Server Error:服务器内部错误
API 测试工具
推荐使用 Apifox 或 Postman 来测试 API 接口,它们可以方便地构造各种请求并查看响应。
🌐 跨域问题详解
跨域是前端开发中最常见的问题之一,理解它的原理和解决方案非常重要。
什么是跨域?
让我们用一个生动的例子来说明:
假设你在 www.baidu.com 网站上,想要请求 www.dy.com 的数据,浏览器会直接阻止这个请求。这就好像你在柬埔寨,想要直接去另一个国家,但没有护照是不允许的。
同源策略(Same-Origin Policy)
同源策略是浏览器的安全机制,它要求:
- 协议相同(http/https)
- 域名相同
- 端口相同
只有三者完全一致,才被认为是"同源",否则就是"跨域"。
在我们的项目中:
- 前端运行在
http://localhost:5173 - 后端运行在
http://localhost:3000
端口不同,所以前端请求后端时会报错跨域。
解决跨域的方法
有两种主要的解决方案:
方法一:后端配置 CORS 中间件(推荐)
就像给前端特批了签证一样,后端允许跨域访问,浏览器就会放行:
import cors from 'cors';
app.use(cors()); // 允许所有域名跨域访问
方法二:前端使用代理转发
- 前端请求自己的 5173 端口
- 5173 端口将请求转发到 3000 端口
这种方法在开发环境中常用,但生产环境通常还是配置 CORS。
🤖 AI 大模型集成详解
这个项目最核心的部分就是将 AI 大模型集成到 Web 应用中,让 AI 帮助我们生成规范的 Git 提交信息。
LangChain 框架
LangChain 是一个强大的大模型应用开发框架,它提供了:
- 模型集成:支持 Ollama、OpenAI 等多种模型
- 提示词模板:方便地构造提示词
- 输出解析器:解析模型的输出
- Chain 链式调用:将多个步骤串联起来
后端 AI 集成代码解析
让我们看看 server/index.js 中的核心代码:
import { ChatOllama } from "@langchain/ollama";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
const model = new ChatOllama({
baseUrl: "http://localhost:11434",
model: "deepseek-r1:8b",
temperature: 0.1 // temperature 越低,输出越稳定、越严格
})
这里创建了一个 ChatOllama 实例,连接到本地的 Ollama 服务,使用 deepseek-r1:8b 模型。temperature 设置为 0.1,让模型的输出更加稳定和可预测。
/chat 接口实现
app.post('/chat', async (req, res) => {
const { message } = req.body;
if (!message || typeof message !== 'string') {
return res.status(400).json({
error: "message 必填,必须是字符串"
})
}
try {
const prompt = ChatPromptTemplate.fromMessages([
['system', 'You are a helpful assistant.'],
['human', '{input}']
]);
const chain = prompt
.pipe(model)
.pipe(new StringOutputParser());
const result = await chain.invoke({
input: message
})
res.json({
reply: result
})
} catch (e) {
res.status(500).json({
error: "调用大模型失败"
})
}
})
这段代码展示了后端开发的最佳实践:
- 参数校验:检查 message 是否存在且是字符串
- 错误处理:使用 try-catch 捕获异常
- 合适的状态码:400 表示客户端错误,500 表示服务器错误
- 统一的响应格式:返回 JSON 格式的数据
⚛️ 前端技术栈详解
React 组件架构
前端使用 React 19,这是目前最新的 React 版本。让我们看看 App.jsx:
import { useEffect } from 'react';
import { chat } from './api/index';
import { useGitDiff } from './hooks/useGitDiff';
export default function App() {
const { loading, content } = useGitDiff();
return (
<div className="flex">
{loading ? 'loading......' : content}
</div>
)
}
Axios 请求封装
在 api/index.js 中,我们封装了 Axios 实例:
import axios from 'axios';
const service = axios.create({
baseURL: 'http://localhost:3000',
headers: {
'Content-Type': 'application/json',
},
timeout: 60000,
});
export const chat = (message) =>
service.post('/chat', { message })
使用 Axios 而不是原生 fetch 的好处:
- 更好的错误处理
- 请求和响应拦截器
- 自动 JSON 转换
- 超时设置
- 统一的 API 管理
自定义 Hook:useGitDiff
React Hook 是 React 16.8 引入的特性,它让我们能够在函数组件中使用状态和其他 React 特性。
import { useState, useEffect } from 'react';
import { chat } from '../api/index.js';
export const useGitDiff = () => {
const [content, setContent] = useState('');
const [loading, setLoading] = useState(false);
useEffect(() => {
(async () => {
setLoading(true);
const { data } = await chat('你好');
setContent(data);
setLoading(false);
})()
}, [])
return {
loading,
content,
}
}
自定义 Hook 的好处:
- 代码复用:将业务逻辑从组件中剥离出来
- 关注点分离:组件只负责 UI 展示,Hook 负责业务逻辑
- 可测试性:Hook 可以独立测试
📝 Git 规范化提交完全指南
为什么要规范化提交?
- 清晰可读:提交信息明确说明变更内容,让任何人都能快速理解
- 追踪问题:便于关联 Bug、任务(如 Jira、Trello)
- 协作效率:团队成员快速理解代码变动,减少沟通成本
- 自动化工具:可以基于提交信息自动生成 CHANGELOG、发布版本
Conventional Commits 标准
业界最流行的提交规范是 Conventional Commits,格式如下:
<类型>: <描述> [选项]
类型(Type)
明确变更的类型,常见选项:
| 类型 | 说明 | 示例 |
|---|---|---|
feat | 新增功能 | feat: 增加用户登录功能 |
fix | 修复 Bug | fix: 修复用户列表渲染错误 |
docs | 文档修改 | docs: 更新 README 文档 |
style | 样式调整 | style: 优化按钮样式 |
refactor | 代码重构 | refactor: 重构用户服务模块 |
test | 测试相关 | test: 增加登录功能测试 |
chore | 构建工具、依赖升级 | chore: 升级 React 到 19.0 |
描述(Description)
- 简短说明变更内容
- 首字母大写
- 使用现在时态(比如用 "Add" 而不是 "Added")
- 不超过 50 个字符
可选部分
BREAKING CHANGE:标记破坏性变更#issue号:关联任务/PR!:标记 Breaking Change(可选,但需团队约定)
示例
feat: 增加用户登录功能
新增登录表单和验证逻辑
fix: 修复用户列表渲染错误
修复因未定义变量导致的报错 #123
docs: 更新 README 文档
添加项目使用说明
如何实现规范化?
方法一:手动规范(新手入门)
直接按照格式编写提交信息,养成良好的习惯:
git commit -m "fix: 修复按钮点击事件未触发的问题 #123"
方法二:使用工具自动化(进阶)
推荐使用以下工具链:
- Husky:配置 Git Hook
- Commitizen:交互式命令生成提交信息
- commitlint:校验提交信息格式
配置步骤(以 Husky + commitlint 为例):
npx husky install
在 package.json 中添加配置:
{
"commitlint": {
"extends": ["@commitlint/config-conventional"]
}
}
新手常见问题
- 提交信息太模糊:避免 "我改了点东西" 这种描述,要明确说明问题或功能
- 不关联 Issue:用
#issue号将提交与任务关联,方便追踪 - 提交频率不合理:推荐"小步提交"(Small Commit),每次解决一个独立问题
- 提交包含太多内容:一个提交应该只做一件事,便于回滚和审查
推荐工具
- ESLint + Prettier:统一代码风格
- GitLens:VS Code 插件,查看提交历史、分支差异
- GitHub/GitLab:使用内置的 PR 审批流程,强制提交模板
🎯 项目运行指南
后端启动
cd server
pnpm install
nodemon index.js
后端服务将在 http://localhost:3000 启动。
前端启动
cd fronted
pnpm install
pnpm dev
前端应用将在 http://localhost:5173 启动。
Ollama 启动
确保 Ollama 正在运行,并且已经拉取了 deepseek-r1:8b 模型:
ollama run deepseek-r1:8b
🚀 总结
这个项目展示了如何构建一个完整的 AI 驱动的全栈应用,涵盖了:
- 前后端分离架构:React + Express 的经典组合
- AI 大模型集成:通过 LangChain + Ollama 集成开源大模型
- 现代化开发工具链:Vite、TailwindCSS、Axios 等
- Git 规范化提交:从理论到实践的完整指南
通过这个项目,不仅可以学习到技术知识,更重要的是理解了如何将 AI 技术应用到实际的开发工作流中,提升开发效率和代码质量。
规范化 Git 提交信息虽然看起来是小事,但它体现了一个开发者的专业素养。希望这个项目能帮助你养成良好的开发习惯,让你的代码提交记录清晰、专业、可追溯!