一、分支管理:搭建 “分工明确” 的协作骨架

混乱的分支体系是团队 Git 协作的万恶之源。想象一下:有人在main分支直接写代码,有人用 “test1”“newcode” 命名分支,合并时根本分不清分支用途 —— 这种场景下,冲突和版本混乱只是时间问题。

1. 推荐:简化版 Git Flow 分支结构

企业级项目中,无需过度复杂的分支模型,一套 “主分支 + 辅助分支” 的简化结构足以满足需求,核心是明确每个分支的 “生命周期” 和 “职责边界”:

分支类型 命名规范 核心用途 操作红线
主分支 main/trunk 存放生产环境代码,始终保持 “可部署” 状态(任何时候拉取都能正常运行) 严禁直接push,仅通过 PR 合并,合并前必须经过测试
开发分支 develop 团队日常开发集成分支,汇总各功能分支代码,是预发布前的 “代码蓄水池” 不直接在该分支写代码,仅接受功能分支合并
功能分支 feature/模块名-需求描述 单个功能 / 需求的独立开发分支(如feature/user-login) 从develop创建,完成后合并回develop,合并后删除
修复分支 hotfix/问题描述 生产环境紧急 bug 修复(如hotfix/pay-timeout) 从main创建,修复后同步合并到main和develop
预发布分支 release/v版本号 发布前的测试分支(如release/v1.3.0) 从develop创建,测试通过后合并到main和develop

2. 分支操作避坑指南

(1)创建分支前,先同步最新代码

这是最容易被忽略但最重要的一步!如果基于旧版本的develop创建功能分支,后续合并时会出现大量 “历史冲突”。正确流程如下:

1
2
3
4
5
6
7
8
# 1. 切换到develop分支
git checkout develop

# 2. 同步远程最新代码(--rebase避免生成多余merge commit)
git pull --rebase origin develop

# 3. 基于最新develop创建功能分支
git checkout -b feature/order-pay

(2)分支 “用完即删”,避免臃肿

功能分支合并到develop后,本地和远程的该分支就失去了价值。及时清理不仅能让分支列表更简洁,还能避免后续误操作:

1
2
3
4
5
# 删除本地分支(-d确保分支已合并,避免误删未合并分支)
git branch -d feature/order-pay

# 删除远程分支
git push origin --delete feature/order-pay

二、提交规范:让每一次提交都 “可追溯”

“改了点东西”“修复 bug”“再改一版”—— 这样的提交信息,在后续定位问题、回滚代码时,会让你陷入 “猜谜游戏”。团队必须统一遵循规范,让提交历史成为 “可阅读的文档”。

1. 提交信息格式:3 部分组成

1
2
3
4
5
<类型>[可选作用域]: <描述>

[可选正文]

[可选脚注]

(1)类型:明确提交目的

  • feat:新增功能(如feat(user): 新增用户注册短信验证)

  • fix:修复 bug(如fix(order): 修复订单金额计算错误)

  • docs:仅修改文档(如docs: 更新API文档参数说明)

  • style:不影响逻辑的格式调整(如缩进、空格,不含代码重构)

  • refactor:代码重构(既不新增功能也不修复 bug,如函数拆分)

  • test:新增 / 修改测试代码(如test: 为登录接口添加单元测试)

  • chore:杂项操作(如依赖升级、构建脚本修改,chore: 升级npm到v10)

(2)作用域:精准定位影响范围

可选字段,指定提交影响的模块(如user用户模块、order订单模块、pay支付模块),便于快速筛选某模块的变更记录。

(3)描述:简洁明了,直击重点

100 字符以内,首字母小写,结尾不加句号。例如 “新增用户登录验证码过期逻辑” 而非 “用户登录相关修改”。

2. 提交实操技巧

(1)小步提交,拒绝 “大爆炸”

一个提交只做一件事!比如 “新增登录接口” 和 “修复登录参数校验” 应拆分为两个提交,而非合并成一个。这样做的好处是:

  • 回滚时能精准控制范围(不会因 “回滚一个 bug 删掉新功能”);

  • 代码审核时,审核者能快速理解每一次变更的意图。

(2)提交前 “三检查”

检查变更内容:执行git diff查看修改的文件和代码,避免误提交本地配置文件(如config.local.js)、日志文件等;

检查忽略文件:确保.gitignore已配置正确,不需要跟踪的文件(如node_modules/、dist/)不会被提交;

检查提交信息:对照规范自查,避免 “格式错误” 或 “描述模糊”。

(3)工具强制规范:从 “人治” 到 “机治”

靠自觉遵守规范难免有疏漏,推荐集成commitlint+husky工具,在提交时自动校验信息格式:

1
2
3
4
5
6
7
8
9
# 1. 安装依赖
npm install --save-dev @commitlint/cli @commitlint/config-conventional husky

# 2. 配置commitlint规则(默认遵循Conventional Commits)
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

# 3. 配置husky钩子,在提交前触发校验
npx husky install
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'

配置后,若提交信息不符合规范,Git 会直接拒绝提交,从工具层面保障规范落地。

三、冲突处理:从 “被动解决” 到 “主动预防”

代码冲突不是 “洪水猛兽”,但处理不当会导致代码丢失、逻辑混乱。核心思路是 “提前预防,规范解决”。

1. 冲突预防:减少冲突发生的概率

(1)高频同步主分支

如果你的功能分支开发周期超过 1 天,每天至少同步一次develop的最新代码。这样能将 “大冲突” 拆分成 “小冲突”,降低解决难度:

1
2
# 在功能分支上,同步develop的最新代码
git pull --rebase origin develop

(2)模块分工明确

团队内提前划分代码模块,比如 A 负责用户登录,B 负责订单管理,避免多人同时修改同一文件的同一部分。若需跨模块修改,提前沟通确认。

(3)不提交大文件

图片、视频、压缩包等大文件(超过 100MB)不适合用 Git 跟踪 —— 会导致仓库体积膨胀,拉取速度变慢,还可能引发不必要的冲突。建议使用对象存储(如阿里云 OSS、AWS S3),Git 仅记录文件的访问链接。

2. 冲突解决:安全第一,逻辑优先

(1)优先用 Rebase,保持提交历史线性

合并主分支代码到功能分支时,优先使用git pull --rebase而非git merge。Rebase 会将你的本地提交 “挪到” 主分支最新提交之后,避免生成冗余的 “merge commit”,提交历史更清晰:

  • 正确:git pull --rebase origin develop(功能分支同步 develop)

  • 避免:git merge origin develop(会生成 merge commit,历史混乱)

⚠️ 注意:已推送到远程的分支,禁止执行 rebase!因为 rebase 会修改历史提交,导致团队其他成员拉取时出现冲突。

(2)三 - way merge:理解冲突再修改

解决冲突时,必须对比三个版本的代码:

  • Current:你本地分支的代码;

  • Incoming:主分支(如 develop)的代码;

  • Base:你和主分支的共同祖先代码。

不要直接删除冲突标记(<<<<<<<、=======、>>>>>>>)或盲目保留某一方代码,要先理解双方的逻辑意图,再结合业务需求修改。例如:

1
2
3
4
5
6
7
8
9
10
// 冲突代码示例
<<<<<<< HEAD // 你的本地代码
function calculatePrice(amount) {
return amount * 0.9; // 你添加的9折逻辑
}
======= // develop分支的代码
function calculatePrice(amount) {
return amount * 0.8 + 10; // 其他人添加的8折+10元运费逻辑
}
>>>>>>> origin/develop

此时需要沟通确认业务规则(是 9 折还是 8 折 + 运费),再修改为正确逻辑,而非直接保留自己的代码。

(3)解决后必须测试

冲突解决后,执行git add 冲突文件标记为已解决,再通过git rebase --continue完成同步。最重要的一步是:本地运行代码测试,确认冲突解决没有破坏原有逻辑(比如是否出现语法错误、功能异常)。

四、安全操作:避免 “不可逆” 的代码丢失

Git 虽有版本回溯能力,但不当操作仍可能导致代码丢失。记住:任何可能修改历史或删除代码的操作,都要谨慎再谨慎

1. 禁止这些 “危险操作”

(1)公共分支禁用git reset --hard

git reset --hard会强制覆盖工作区和暂存区,且未提交的代码无法恢复。如果需要回滚已提交的代码,应使用git revert(创建一个新的 “回滚提交”,保留历史记录):

1
2
3
4
5
# 错误:公共分支用reset --hard回滚
git reset --hard HEAD~1 # 会删除最新的1个提交,且无法恢复

# 正确:用revert回滚
git revert HEAD # 创建一个新提交,抵消最新提交的修改

(2)公共分支禁用git push -f

git push -f(强制推送)会覆盖远程分支的历史,导致团队其他成员的本地分支与远程不一致,引发大规模冲突。如果确实需要强制推送(如个人功能分支 rebase 后),必须先确认:

  • 该分支只有你一人使用;

  • 提前告知团队成员,让他们先备份代码。

2. 未完成代码:用git stash临时保存

如果需要切换分支,但当前代码未完成不想提交,使用git stash保存:

1
2
3
4
5
6
7
8
# 保存未完成的代码,备注说明
git stash save "未完成的订单支付功能"

# 切换到其他分支
git checkout develop

# 后续恢复代码
git stash pop # 恢复最近一次stash的代码,并删除该stash记录

3. 核心分支:定期备份

对main、develop等核心分支,建议每月创建一次备份分支,防止极端情况下分支被误删或破坏:

1
2
3
4
# 为main分支创建备份
git checkout main
git checkout -b main-backup-20240601
git push origin main-backup-20240601