Git 团队协作工作流实战手册

前言

在大三的课程项目和实习中,我从"一个人写代码"过渡到了"多人协作开发"。Git 不再只是 commitpush,分支策略、代码审查、冲突解决——这些才是真正考验协作能力的地方。这篇文章总结我在实际项目中积累的 Git 工作流经验。

为什么要用分支策略

没有分支策略的团队就像没有交通规则的十字路口——迟早会撞车。一个好的分支策略能带来:

  • 并行开发:多人同时开发不同功能,互不干扰
  • 版本可控:随时知道哪个版本对应哪些功能
  • 快速修复:线上出 Bug 能不动正在开发的功能就修复
  • 可追溯性:每个功能都有清晰的历史记录

Git Flow:经典但偏重

master ──────●────────────●────────────●──→ 生产版本
              \          /            /
develop ──────●──●──●──●────●──●────●──→ 开发主干
               \  /    \  /      \  /
feature/A ─────●──●     \        /
                         \      /
feature/B ────────────────●──●──●
                                 \
hotfix ───────────────────────────●──→ 紧急修复

Git Flow 定义了五种分支:

分支 用途 生命周期
master/main 生产代码 永久
develop 开发主干 永久
feature/* 功能开发 功能合并后删除
release/* 版本发布准备 发布后删除
hotfix/* 紧急修复 修复后删除

适用场景:有固定发布周期的传统项目,版本号明确。

缺点:分支太多,对小型团队来说过于繁重。

Trunk-Based Development:轻量高效

main ──●──●──●───●──●──●──→ 主干
        \  /    /  /  /
feat/A ──●     /  /  /
feat/B ───────●  /  /
feat/C ──────────●  /
fix/D ──────────────●

核心理念:所有人都直接在 main 上工作,短期分支快速合并。

规则很简单:
- 分支生命周期不超过 1-2 天
- 使用 Feature Flag 控制功能开关
- 高频提交、高频合并
- CI/CD 确保每次合并都是可部署的

适用场景:持续交付团队、中小型项目。我个人更倾向于这种方式。

我们团队的实际工作流

综合 Git Flow 和 Trunk-Based 的优点,我们的工作流:

main ←──────── PR ←── feat/user-auth
  ↑                    ↑
  │                    │
  └── 部署到生产       └── 开发中

分支命名规范

feat/user-login          # 新功能
fix/order-timeout        # Bug 修复
refactor/payment-module  # 重构
docs/api-documentation   # 文档
chore/update-deps        # 杂项(依赖更新等)

标准操作流程

# 1. 从最新的 main 创建功能分支
git checkout main
git pull origin main
git checkout -b feat/user-profile

# 2. 开发过程中频繁提交
git add .
git commit -m "feat: add user profile page"

# 3. 合并 main 的最新代码(解决冲突)
git checkout main && git pull
git checkout feat/user-profile
git merge main

# 4. 推送并创建 Pull Request
git push origin feat/user-profile
# 然后在 GitHub/GitLab 上创建 PR

Commit Message 规范

好的提交信息是给自己和团队的一份礼物。我们采用 Conventional Commits 规范:

<type>(<scope>): <subject>

<body>

<footer>

Type 类型

Type 说明 示例
feat 新功能 feat: add user avatar upload
fix Bug 修复 fix: resolve order timeout on high load
refactor 重构 refactor: extract payment service
docs 文档 docs: update API documentation
style 格式 style: format code with prettier
test 测试 test: add unit tests for auth module
chore 杂项 chore: update dependencies
perf 性能优化 perf: optimize image compression

好的提交 vs 坏的提交

❌ 修了个bug
❌ update
❌ 改了点什么
❌ WIP

✅ fix: resolve null pointer when user avatar is empty
✅ feat(auth): add JWT token refresh mechanism
✅ refactor: extract validation logic to middleware

一个关键原则:每个 commit 只做一件事。如果一个 commit 消息里有"和",考虑拆成两个。

Pull Request / Merge Request 最佳实践

PR 应该包含什么

一个合格的 PR 应该包含:

  1. 清晰的标题:用 Conventional Commits 格式
  2. 描述
  3. 做了什么(What)
  4. 为什么这么做(Why)
  5. 怎么做的——技术方案简述(How)
  6. 测试情况
  7. 截图或演示(前端变动)
  8. 关联 IssueCloses #123
## 做了什么
实现了用户头像上传功能,支持裁剪和压缩。

## 为什么
用户反馈缺少个性化设置,头像是最基本的需求。

## 技术方案
- 前端使用 cropper.js 实现裁剪
- 后端使用 sharp 库压缩图片
- 上传至 OSS,数据库存储 URL

## 测试
- 上传 JPG/PNG/WebP 各一张,均正常
- 超过 10MB 的文件正确拒绝
- 未登录上传返回 401

## 截图
![avatar upload](screenshot.png)

Closes #42

Code Review 礼仪

Reviewer(审查者)
- 关注逻辑和设计,而非代码风格(让 Linter 处理)
- 区分"必须改"和"建议改"
- 提出问题而非指令:"这里用递归会不会有栈溢出风险?"

Author(作者)
- PR 尽量小(控制在 400 行以内)
- 每个评论都要回复(哪怕只是 )
- 被指出问题不要 defensive——这是学习机会

Merge 策略选择

策略 效果 适合场景
Merge Commit 保留完整分支历史 需要追溯每个功能的场景
Squash Merge 将所有 commit 合并为一个 功能分支 commit 较乱时
Rebase Merge 线性历史,无 merge commit 追求干净历史的团队

我们团队的选择:功能分支用 Squash Merge,hotfix 用 Rebase Merge。

# Squash Merge 效果
Before: feat: wip  feat: continue  feat: done
After:  feat: add user avatar upload (1 commit)

# Rebase Merge 效果
Before: main  feat 分支交错
After: 一条干净的线

冲突解决实战

冲突是协作的自然产物,不应该害怕它。

# 遇到冲突时
git merge main
# CONFLICT in src/user/controller.js

# 查看冲突文件
git status

# 解决冲突(手动编辑文件,删除 <<<<<< ==== >>>>>> 标记)

# 标记已解决
git add src/user/controller.js
git commit -m "merge: resolve conflict with main"

实用技巧

# 使用可视化工具解决冲突
git mergetool

# 完全接受某一方的版本
git checkout --theirs src/user/controller.js   # 接受 main 分支的
git checkout --ours src/user/controller.js     # 保留自己的

常见失误与补救

1. 不小心 commit 到错误的分支

# 把最近的 commit 移到正确的分支
git checkout correct-branch
git cherry-pick <commit-hash>
git checkout wrong-branch
git reset --hard HEAD~1

2. commit 信息写错了

# 修改最近一次 commit 信息
git commit --amend -m "正确的信息"

3. 不小心 push 了不该 push 的文件

# 从 Git 历史中移除敏感文件
git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch config/secrets.json" \
  --prune-empty --tag-name-filter cat -- --all

4. 回退已经 push 的 commit

# 创建反向 commit(安全)
git revert <commit-hash>
git push

# 强制覆盖(危险!只在个人分支使用)
git reset --hard <commit-hash>
git push --force

Git Alias 提效

~/.gitconfig 中配置别名:

[alias]
    co = checkout
    br = branch
    ci = commit
    st = status
    lg = log --oneline --graph --all --decorate
    unstage = reset HEAD --
    last = log -1 HEAD
    undo = reset --soft HEAD~1
    prune-local = !git branch --merged | grep -v '\\*\\|main\\|master' | xargs -r git branch -d

总结

Git 不只是"保存代码"的工具,它是团队协作的语言。总结几个核心原则:

  1. 小步提交:每个 commit 原子化,方便回退和审查
  2. 规范命名:分支名、commit 信息都遵循约定
  3. 及时同步:经常 merge main,避免积压大量冲突
  4. Code Review:把它当作学习机会,不是找茬
  5. 善用工具git lg 查看历史、git stash 暂存临时代码、git bisect 定位 Bug

这些经验来自大三一年里 5 个以上实际项目的协作实践。Git 从"必须用的工具"变成了"帮我省事的工具"——这个转变,需要的就是刻意练习和团队约定。


本文基于 ERP 系统、灵山胜境等多个团队项目的实际 Git 工作流经验总结。

posted @ 2026-07-01 16:56  C(5,3)  阅读(10)  评论(0)    收藏  举报