Git 团队开发指南:从一个人堆代码到多人协作
写在前面
今年暑假实习的时候,跟我一块儿实习的一个中南大学研究生,每次合并代码要么是交给我合,要么是直接把别人代码给覆盖了。上个月我教他怎么用 Git 提 PR、怎么做团队分支管理,才意识到一件事:很多同学其实没有真正接触过团队开发。
不只是他。之前学校做课设匹配到的队友,很多人也没用过 GitHub 或者 Gitee;包括我们实验室的一些研究生,本地使用 Git 最多也就是一个人往仓库里堆东西。没有亲手做过多人协作,确实很难理解 Git 这些流程是为了什么。
这篇博客就把我常用的那套流程整理出来,方便以后给朋友学习。如果看完还有疑问,直接来问我。
下面这些对话,就是我当时教他时真实发生的。不是段子,是团队开发里每天都在上演的场景。
四个与研究生真实协作的场景
场景一:不知道要先拉取最新代码
场景二:试图用 force 解决冲突
场景三:误删 .gitignore 导致本地配置被跟踪
场景四:找我直接去对方电脑操作上传
这些对话暴露的问题都很典型:不知道什么时候拉最新代码、想用 force push 硬覆盖冲突、乱动 .gitignore 影响别人、以及完全不知道正确的协作流程。这也是为什么我觉得有必要把标准流程一次写清楚。
为什么要学这套流程?
很多人初学 Git 只学到三步:
1 | git add . |
这三步在你自己一个人的项目里够用了。但一到团队里就会出各种问题:
- 两个人改了同一个文件,后提交的人直接把先提交的人的代码覆盖了;
- 功能写到一半,主分支已经更新了,合进去全是冲突;
- 线上出 bug,不知道哪个提交导致的,也回退不了;
- 代码审阅(Code Review)没法做,出了问题只能互相甩锅。
Git 的分支、PR、commit 规范,本质上就是解决这些问题的。下面直接上操作流程。
代码提交流程
1. clone 仓库
先把远程仓库下载到本地:
1 | git clone https://github.com/CreatureK/Teaching-Assistance.git |
下载完后进入项目目录:
1 | cd Teaching-Assistance |
2. 保证 main 分支最新
在创建自己的开发分支之前,一定要先拉取主分支最新代码。这是为了避免你基于一个过时的版本开发,最后合进去产生大量冲突。
1 | git checkout main |
如果你用的主分支叫
master,把main换成master。
3. 创建并切换到开发分支
不要直接在 main 上写代码。团队开发每个人都在自己的分支上写,写完通过 PR 合并进去。
1 | git checkout -b feature/<name>-<date>-<description> |
例如:
1 | git checkout -b feature/CreatureK-20250508-add-dev-doc |
也可以分两步:
1 | git branch feature/CreatureK-20250508-add-dev-doc |
分支前缀说明
| 前缀 | 含义 | 使用场景 |
|---|---|---|
feature/ |
新功能 | 开发新模块、新页面、新接口 |
fix/ |
修复 bug | 修线上问题或测试发现的 bug |
docs/ |
文档 | 修改 README、接口文档、注释 |
test/ |
测试 | 补充测试用例 |
release/ |
发布 | 准备发版、打 tag |
命名里的 name 一般写你的名字缩写或 GitHub 用户名,date 写创建日期,description 用简短英文说明这个分支做什么。这样一眼就能知道分支是谁的、什么时候建的、干什么的。
4. 开发并提交
改完代码后,按下面三步提交:
1 | git add . |
git add . 的注意事项
git add . 会把当前目录下所有改动都加进暂存区。如果你确定所有改动都是本次要提交的,可以用它;如果你只改了某几个文件,建议单独添加:
1 | git add src/main/java/com/example/UserService.java |
养成检查改动的习惯,别把一些临时文件、配置文件或者自己的测试数据也提交上去。
5. 在 GitHub 上发起 Pull Request
提交到远程分支后,去 GitHub 仓库页面,一般会看到一个黄色的提示条:Compare & pull request。点击它,填写 PR 标题和描述,然后提交。
PR 标题通常和 commit 信息保持一致,比如 feat(backend): add dev doc。
PR 描述里可以写清楚:
- 这个改动做了什么;
- 为什么需要这个改动;
- 有没有需要 reviewer 特别注意的地方;
- 是否经过本地测试。
然后 @ 你的队友或者负责人来 Review。Reviewer 审阅通过后,才能合并到 main。
永远不要在本地直接
git push origin main把代码推到主分支。 这是团队开发的大忌。
commit 信息格式
我常用的 commit 格式是:
1 | <任务分类>(<任务范围>): <任务描述> |
例如:
1 | feat(backend): add dev doc |
任务分类
| 类型 | 含义 | 对应分支 |
|---|---|---|
feat |
新功能 | feature/ |
fix |
修复 bug | fix/ |
docs |
文档 | docs/ |
test |
测试 | test/ |
release |
发布 | release/ |
refactor |
重构 | feature/ 或 fix/ |
chore |
杂项、构建、依赖 | 视情况 |
任务范围
范围表示这次改动影响的是哪个模块。常见写法:
| 范围 | 说明 |
|---|---|
backend |
后端代码 |
frontend |
前端代码 |
docs |
文档 |
test |
测试 |
ci |
持续集成配置 |
api |
接口 |
如果一次改动涉及多个范围,或者不太好归类,可以省略范围,只写类型和描述。
任务描述
描述用简洁的英文或中文说明做了什么。注意:
- 用祈使句,例如
add dev doc,不是added dev doc; - 不要写「修改」「更新了」这种模糊词;
- 如果改动比较复杂,可以在 commit 标题后空一行写详细说明。
1 | git commit -m "feat(backend): add dev doc |
规范的 commit 信息有两个好处:
- 看 Git 历史时一目了然;
- 很多项目会用 commit 信息自动生成 CHANGELOG。
多人协作时常见的几个问题
冲突怎么办?
当你准备 push 或者 merge 的时候,如果提示 conflict,说明你和别人改了同一个地方。不要慌,按下面步骤处理:
1 | git pull origin main |
把主分支最新代码拉下来,Git 会尝试自动合并。如果自动合并不了,会在文件里标出来冲突位置:
1 | 别人的代码 |
你手动编辑文件,保留正确的那部分,删掉 <<<<<<<、=======、>>>>>>> 这些标记,然后重新提交:
1 | git add . |
解决冲突时一定要仔细看,不要无脑保留自己的代码把别人的覆盖了。
想撤销上一次提交怎么办?
如果只是本地提交,还没 push:
1 | git reset --soft HEAD~1 |
这会撤销最近一次 commit,但保留你的改动,你可以修改后重新提交。
如果已经 push 到远程了,不要乱用 reset,更安全的做法是:
1 | git revert HEAD |
revert 会生成一个新的提交,把上一次提交的改动反向抵消掉,不会破坏历史。
开发到一半要切分支怎么办?
代码写到一半,突然要修一个紧急 bug,但当前改动还没法提交。可以用 stash 暂存:
1 | git stash |
然后切到 fix/ 分支修 bug。修完再切回来,把暂存的改动弹出来:
1 | git stash pop |
主分支更新了,怎么同步到自己的分支?
在自己的 feature 分支上执行:
1 | git pull origin main |
或者更规范一点:
1 | git fetch origin |
这会把主分支的最新改动合并进你的 feature 分支。建议经常做这件事,不要等到最后一次性合,否则冲突会很难处理。
一条完整的开发流水线
假设你要新增一个用户登录功能,完整流程应该是这样:
1 | # 1. 切换到主分支并更新 |
写在最后
Git 本身不难,难的是养成团队开发的意识:
- 不要在主分支直接改代码;
- 不要直接覆盖别人的改动;
- 提交前先拉最新代码;
- commit 信息写清楚,方便以后查问题;
- 改动必须经过 Review 再合并。
这些规则不是形式主义,而是为了避免在多人协作时把项目搞乱。我也是之前在实验室跟兵哥学来的,现在传给你们。
如果看完还有不懂的地方,欢迎来问我。
