Git 最佳实践

Git 最佳实践

概述

本文档规定了项目的 Git 提交信息规范,采用 Conventional Commits 格式,确保提交历史清晰易读、便于追溯。

Commit Message 格式

基本结构

xml 复制代码
<type>(<scope>): <subject>

[可选 body]

[可选 footer]

示例:

bash 复制代码
feat(router): 新增虚拟路由插件支持动态路由

实现了基于 Vue Router 的虚拟路由插件,支持:
- 动态路由注册
- 路由守卫自动绑定
- 路由缓存管理

Closes #123

必填字段

Type 类型
Type 说明 使用场景
feat 新功能 添加新特性、新模块
fix Bug 修复 修复缺陷、错误
docs 文档 更新文档、注释
style 代码格式 格式化代码、调整缩进、优化导入等(不影响功能)
refactor 重构 重构代码逻辑(不改变功能)
perf 性能优化 提升性能、优化算法
test 测试 添加/修改测试
chore 构建/工具 修改配置、构建脚本、依赖管理
revert 回滚 回滚之前的提交
Scope 范围

范围应该是受影响的业务模块或功能,使用 kebab-case

业务模块示例:

复制代码
purchase, supplier, contract, requisition, approval, inventory

功能模块示例:

复制代码
login, dashboard, settings, report, notification, workflow

其他:

arduino 复制代码
config, build, ci, docs, deps

💡 Scope 应根据实际业务场景命名,上述仅为示例。建议团队内部统一约定常用的 scope 列表。

Subject 主题
  • ✅ 使用中文描述
  • ✅ 使用动词开头,现在时态(如:新增、修复、优化)
  • 首字母小写
  • 不超过 50 个字符
  • 结尾不加句号

可选字段

Body 正文

对于复杂的提交,使用多行 body 详细说明:

  • 说明修改的原因和背景
  • 描述具体实现的功能点
  • 列出重要的技术细节

格式: 与 subject 之间空一行

bash 复制代码
feat(wormhole): 新增 Swagger API 自动生成功能

实现了从 Swagger 文档自动生成 API 代码的功能,包括:
- 自动解析 Swagger/OpenAPI 文档
- 生成 TypeScript 类型定义
- 生成 API 函数代码
- 自动生成 Mock 数据
- 支持 Alova 实例自动检测

该功能可大幅提高 API 接口对接效率,减少手写重复代码。

用于关联 Issue 或标记破坏性变更:

关联 Issue:

bash 复制代码
fix(router): 修复路由缓存失效问题

修复了在特定场景下路由缓存失效的问题。

Closes #123
Fixes #456

破坏性变更 (Breaking Changes):

bash 复制代码
feat(api): 重构 API 请求接口

重构了整个 API 请求模块,采用新的 Alova 实例创建方式。

BREAKING CHANGE: createAppAlova 方法签名已更改。
旧版本: createAppAlova(baseURL, timeout)
新版本: createAppAlova({ baseURL, timeout, ...options })

迁移指南:将所有 createAppAlova 调用更新为对象参数形式。

提交示例

✅ 正例

bash 复制代码
# 新功能
feat(purchase): 新增采购申请单批量审批功能
feat(supplier): 实现供应商信息批量导入功能
feat(contract): 新增合同电子签章功能
feat(requisition): 新增请购单高级搜索筛选条件

# Bug 修复
fix(login): 修复登录失败后跳转错误
fix(approval): 修复审批流程状态更新失败的问题
fix(inventory): 修复库存数量显示不正确的问题
fix(notification): 修复消息通知未实时更新的问题

# 文档更新
docs(readme): 更新项目安装说明
docs(api): 补充采购单接口调用文档
docs(workflow): 完善审批流程配置说明

# 代码格式
style(supplier): 格式化供应商模块代码
style(dashboard): 调整仪表盘组件导入顺序

# 重构
refactor(approval): 重构审批流程逻辑
refactor(purchase): 优化采购单查询流程

# 性能优化
perf(dashboard): 优化仪表盘数据加载性能
perf(requisition): 减少请购单列表查询时间

# 测试
test(contract): 添加合同创建流程单元测试
test(approval): 补充审批功能测试用例

# 构建/工具
chore(vite): 更新 Vite 构建配置
chore(deps): 升级 Vue 到 3.4.0
chore(eslint): 调整 ESLint 规则配置

# 回滚
revert(approval): 回滚审批流程优化提交

回滚提交 a1b2c3d,该优化导致某些场景下审批失败。

❌ 反例

bash 复制代码
# 缺少 type
(purchase): 新增采购申请单
purchase: 新增采购申请单

# 缺少 scope
feat: 新增采购申请单
fix: 修复问题

# scope 使用大写或驼峰
feat(Purchase): 新增采购申请单
feat(purchaseOrder): 新增采购申请单

# 使用英文主题(应使用中文)
feat(purchase): add purchase order
fix(supplier): fix supplier bug

# 主题过长(超过 50 字符)
feat(purchase): 新增采购管理功能包括采购申请、采购审批、采购执行、采购统计等完整功能

# 结尾加句号
feat(purchase): 新增采购申请单。

# 主题不清晰
feat(purchase): 更新代码
fix(supplier): 修复问题
chore: 更新

Git 常用操作

1. 查看状态和历史

bash 复制代码
# 查看当前状态
git status

# 查看提交历史(推荐)
git log --oneline --graph --decorate

# 查看某个文件的提交历史
git log --follow -- src/views/purchase/index.vue

# 按作者过滤
git log --author="张三"

# 按模块过滤
git log --grep="purchase"

2. 提交代码

bash 复制代码
# 添加所有修改的文件
git add .

# 添加指定文件
git add src/views/purchase/index.vue

# 提交代码
git commit -m "feat(purchase): 新增采购申请单列表"

# 查看提交结果
git log -1

3. 分支操作

bash 复制代码
# 查看所有分支
git branch -a

# 创建并切换到新分支
git checkout -b feature/purchase-list

# 切换分支
git checkout develop

# 删除本地分支
git branch -d feature/purchase-list

4. 同步代码

bash 复制代码
# 拉取远程最新代码
git pull origin develop

# 推送到远程
git push origin feature/purchase-list

# 第一次推送(关联远程分支)
git push -u origin feature/purchase-list

5. 暂存修改

使用场景: 临时切换分支但不想提交当前修改

bash 复制代码
# 暂存当前修改
git stash save "采购单开发进行中"

# 查看暂存列表
git stash list

# 恢复暂存(保留暂存记录)
git stash apply

# 恢复暂存(删除暂存记录)
git stash pop

6. 查看差异

bash 复制代码
# 查看工作区修改
git diff

# 查看已暂存的修改
git diff --cached

# 查看两个分支的差异
git diff develop feature/purchase-list

7. 撤销和回退(本地未推送)

使用场景: 本地修改错了或提交错了,想要撤销

bash 复制代码
# 撤销工作区的修改
git checkout -- src/views/purchase/index.vue

# 撤销暂存区的修改(保留工作区修改)
git reset HEAD src/views/purchase/index.vue

# 回退到上一个提交(保留修改)
git reset --soft HEAD^

# 回退到上一个提交(丢弃修改)
git reset --hard HEAD^

# 回退到指定提交
git reset --hard a1b2c3d

⚠️ 注意: reset 会改变提交历史,只能在本地未推送时使用

8. 恢复误删(reflog)

使用场景: 误删了分支或回退过头了

bash 复制代码
# 第1步:查看所有操作记录
git reflog

# 第2步:找到想要恢复的提交,比如 d4e5f6g

# 第3步:恢复到那个提交
git reset --hard d4e5f6g

# 或者创建新分支指向那个提交
git checkout -b recovered-branch d4e5f6g

9. 合并分支(merge)

使用场景: 将一个分支的修改合并到当前分支

bash 复制代码
# 合并指定分支到当前分支
git merge feature/purchase-list

# 合并但不自动提交(可以先检查)
git merge feature/purchase-list --no-commit

# 放弃合并
git merge --abort

示例: 功能开发完成后,将 feature 分支合并到 develop 分支

10. 解决冲突

使用场景: 合并或拉取代码时出现冲突

bash 复制代码
# 第1步:查看冲突文件
git status

# 第2步:手动编辑冲突文件,解决冲突标记
# <<<<<<< HEAD
# 当前分支的内容
# =======
# 要合并进来的内容
# >>>>>>> feature/purchase-list

# 第3步:标记冲突已解决
git add src/views/purchase/index.vue

# 第4步:完成合并
git commit  # 如果是 merge
git rebase --continue  # 如果是 rebase
git cherry-pick --continue  # 如果是 cherry-pick

提示: 使用 VSCode 等编辑器可以更方便地解决冲突

11. 挑选提交(cherry-pick)

使用场景: 需要把某个分支的特定提交应用到当前分支

bash 复制代码
# 将某个提交应用到当前分支
git cherry-pick a1b2c3d

# 挑选多个提交
git cherry-pick a1b2c3d e4f5g6h

# 挑选提交范围(不包含 start)
git cherry-pick start..end

# 挑选时发生冲突,解决后继续
git cherry-pick --continue

# 放弃挑选
git cherry-pick --abort

示例: 在 feature 分支修复了一个 bug,现在需要把这个修复应用到 master 分支

12. 反向提交(revert)

使用场景: 已经推送到远程的提交需要撤销

bash 复制代码
# 创建一个反向提交来撤销某次提交(推荐,不改变历史)
git revert a1b2c3d

# 反向提交但不自动提交(可以修改提交信息)
git revert a1b2c3d --no-commit

# 撤销合并提交
git revert -m 1 a1b2c3d  # -m 1 表示保留第一个父节点

示例: 某个功能提交后发现有问题,但已经推送到远程,使用 revert 创建一个新提交来撤销

13. 标签管理

使用场景: 版本发布时打标签,方便版本管理

bash 复制代码
# 查看所有标签
git tag

# 创建标签
git tag v1.0.0

# 创建带说明的标签
git tag -a v1.0.0 -m "发布 1.0.0 版本"

# 给指定提交打标签
git tag v1.0.0 a1b2c3d

# 推送标签到远程
git push origin v1.0.0

# 推送所有标签
git push origin --tags

# 删除本地标签
git tag -d v1.0.0

# 删除远程标签
git push origin --delete v1.0.0

14. 文件修改追溯(blame)

使用场景: 追溯某行代码是谁写的,什么时候写的

bash 复制代码
# 查看文件每行的最后修改记录
git blame src/views/purchase/index.vue

# 查看指定行范围
git blame -L 10,20 src/views/purchase/index.vue

# 查看详细信息(显示邮箱)
git blame -e src/views/purchase/index.vue

# 配合 show 查看完整提交
git show a1b2c3d

技巧: 在 VSCode 中安装 GitLens 插件,鼠标悬停在代码行上即可看到提交信息

15. 清理操作

使用场景: 清理本地无用的分支和文件

bash 复制代码
# 查看远程已删除但本地还存在的分支
git remote prune origin --dry-run

# 删除远程已删除的本地分支
git remote prune origin

# 删除已合并的本地分支
git branch --merged | grep -v "master\|develop" | xargs git branch -d

# 清理未跟踪的文件(谨慎使用)
git clean -fd

# 查看会删除哪些文件(不实际删除)
git clean -fd --dry-run

示例: 远程分支已经删除,但本地还有很多旧分支,用 prune 清理

常见问题

Q1: 如何选择合适的 type?

原则: 根据修改的主要内容选择:

  • 新增功能 → feat
  • 修复 Bug → fix
  • 更新文档 → docs
  • 调整格式 → style
  • 重构代码 → refactor
  • 性能优化 → perf
  • 测试相关 → test
  • 构建/配置 → chore

判断技巧:

  • 如果用户能感知到变化 → feat 或 fix
  • 如果只是内部优化 → refactor 或 perf
  • 如果只改格式不改逻辑 → style
  • 如果改配置/依赖 → chore

Q2: scope 应该写多详细?

建议: 使用顶层模块名即可,不要过于详细:

bash 复制代码
# ✅ 推荐
feat(purchase): 新增采购申请单审批

# ❌ 过于详细
feat(purchase/approval): 新增采购申请单审批
feat(src/views/purchase/approval): 新增采购申请单审批

特殊情况: 如果修改影响多个模块,可以选择:

bash 复制代码
# 方案 1: 使用多个 scope
feat(purchase,approval): 新增采购申请和审批功能

# 方案 2: 使用更通用的 scope
feat(system): 新增系统核心功能

# 方案 3: 省略 scope(不推荐)
feat: 新增核心功能

Q3: 什么时候需要写 body?

需要 body 的情况:

  • 复杂功能,需要说明实现细节
  • 破坏性变更,需要说明迁移方法
  • 重大重构,需要说明原因和影响

不需要 body 的情况:

  • 简单的功能新增
  • 明显的 Bug 修复
  • 文档更新
  • 代码格式调整

Q4: 代码冲突了怎么办?

场景: 合并代码或拉取代码时出现冲突

bash 复制代码
# 第1步:查看冲突的文件
git status

# 第2步:手动编辑冲突文件,解决冲突标记
# <<<<<<< HEAD
# 你的修改
# =======
# 别人的修改
# >>>>>>> feature/purchase-list

# 第3步:标记冲突已解决
git add src/views/purchase/index.vue

# 第4步:继续合并
git commit  # 如果是 merge
git rebase --continue  # 如果是 rebase
git cherry-pick --continue  # 如果是 cherry-pick

技巧:

  • 使用 VSCode,可以点击"接受当前更改"/"接受传入更改"快速解决
  • 不确定时可以先 git merge --abort 取消合并,询问同事后再操作

Q5: 如何撤销已合并的分支?

场景: master 由 feat-a 和 feat-b 合并而成,现在不想要 feat-a 的功能

方法一:使用 revert(推荐,适合已推送到远程)

bash 复制代码
# 第1步:查看合并历史
git log --oneline --graph

# 输出类似:
# d4e5f6 (HEAD -> master) Merge branch 'feat-b'
# a1b2c3 Merge branch 'feat-a'  ← 要撤销这个合并

# 第2步:撤销 feat-a 的合并提交
git revert -m 1 a1b2c3

# -m 1 的含义:
# 合并提交有两个父节点,1 是 master,2 是 feat-a
# -m 1 表示保留 master 的内容,撤销 feat-a 的内容

# 第3步:推送到远程
git push origin master

方法二:使用 reset(只适合本地未推送)

bash 复制代码
# 第1步:找到合并 feat-a 之前的提交
git log --oneline
# 找到 feat-a 合并之前的 commit hash,比如 xyz789

# 第2步:回退到那个提交
git reset --hard xyz789

# 第3步:重新合并 feat-b
git merge feat-b

选择建议:

  • master 已推送到远程,团队成员在使用 → 用 revert
  • 只在本地操作,还没推送 → 用 reset

Q6: 误删了分支/提交怎么恢复?

场景: 不小心删除了分支或回退过头了

bash 复制代码
# 第1步:查看所有操作记录
git reflog

# 输出类似:
# a1b2c3d HEAD@{0}: reset: moving to HEAD^
# d4e5f6g HEAD@{1}: commit: feat(purchase): 新增采购单
# h7i8j9k HEAD@{2}: commit: fix(supplier): 修复供应商

# 第2步:找到想要恢复的提交,比如 d4e5f6g

# 第3步:恢复到那个提交
git reset --hard d4e5f6g

# 或者创建新分支指向那个提交
git checkout -b recovered-branch d4e5f6g

Q7: 如何临时切换分支但不想提交当前修改?

场景: 正在开发功能,突然需要切换到别的分支修 bug,但当前代码还不想提交

使用 stash(推荐)

bash 复制代码
# 第1步:暂存当前修改
git stash save "采购单开发进行中"

# 第2步:切换到其他分支
git checkout hotfix/urgent-bug

# 第3步:修完 bug 后,切回原分支
git checkout feature/purchase-list

# 第4步:恢复之前的修改
git stash pop

Q8: 如何挑选特定的多个提交?

场景: master 分支有 10 次提交,想把其中的第 1、3、5、7、9 次提交抽出来

bash 复制代码
# 第1步:查看提交历史,找到对应的 commit hash
git log --oneline master

# 假设输出:
# j10 第10次提交
# i9  第9次提交  ← 要
# h8  第8次提交
# g7  第7次提交  ← 要
# f6  第6次提交
# e5  第5次提交  ← 要
# d4  第4次提交
# c3  第3次提交  ← 要
# b2  第2次提交
# a1  第1次提交  ← 要

# 第2步:创建新分支(或切换到目标分支)
git checkout -b selected-commits

# 第3步:挑选这些提交
git cherry-pick a1 c3 e5 g7 i9

Q9: merge 和 rebase 的区别?

merge(合并):

bash 复制代码
git checkout develop
git merge feature/purchase-list

# 结果:保留所有提交历史,产生一个合并提交
# develop: A - B - C - M (merge commit)
#                    /
# feature:      D - E

rebase(变基):

bash 复制代码
git checkout feature/purchase-list
git rebase develop

# 结果:将 feature 的提交"移动"到 develop 最新提交之后
# develop: A - B - C - D' - E'

选择建议:

  • 公共分支(develop、master)→ 用 merge(保留完整历史)
  • 个人分支整理提交 → 用 rebase(保持线性历史)
  • 已经推送到远程的分支 → 不要用 rebase(会造成冲突)

Q10: pull 和 fetch 的区别?

区别:

bash 复制代码
# fetch: 只下载远程代码,不合并
git fetch origin develop

# 此时可以先查看差异
git diff develop origin/develop

# 确认没问题后再手动合并
git merge origin/develop

# pull: 下载并自动合并(相当于 fetch + merge)
git pull origin develop

推荐用法:

  • 不确定远程有什么改动 → 先用 git fetch,查看后再合并
  • 确定可以直接合并 → 用 git pull

Q11: 如何修改历史提交信息?

场景: 最近几次提交的信息写错了,想批量修改

bash 复制代码
# 修改最近 3 次提交
git rebase -i HEAD~3

# 会打开编辑器,显示:
# pick a1b2c3d feat(purchase): 新增采购单
# pick d4e5f6g fix(supplier): 修复供应商
# pick h7i8j9k docs(readme): 更新文档

# 将要修改的提交的 pick 改为 reword:
# reword a1b2c3d feat(purchase): 新增采购单
# pick d4e5f6g fix(supplier): 修复供应商
# pick h7i8j9k docs(readme): 更新文档

# 保存后,会依次让你修改每个标记为 reword 的提交信息

⚠️ 注意: 只能修改未推送到远程的提交,否则会造成历史冲突

相关文档

相关推荐
崔庆才丨静觅6 分钟前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60611 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax