一、 引言:从独奏到交响乐
在前面的章节中,我们学习了Git的本地操作和基本的远程仓库管理,这相当于一个音乐家的独奏练习。但软件开发的魅力在于协作,就像一支交响乐团需要多位乐手默契配合才能奏出和谐的乐章。
多人协作是Git最强大的应用场景,也是每个开发者必须掌握的核心技能。在实际项目中,如何让多位开发者同时工作在不同的功能上而互不干扰?如何高效地集成代码?如何解决不可避免的冲突?本章将通过完整的实战演示,带你深入理解企业级的多人协作开发流程。
二、 多人协作的基本工作模式
2.1 协作前的准备工作
为了模拟真实的多人协作环境,我们需要:
-
一个共享的远程仓库:在Gitee上创建的项目仓库。
-
多个开发者账号:模拟两个或多个开发者共同参与项目。
-
明确的分支策略:约定好如何创建和使用分支。
我们的模拟场景:
-
开发者A :在Linux环境下工作,用户名为
liu -
开发者B :在Windows环境下工作,用户名为
liu-teammate -
项目仓库 :
git_teaching(已在Gitee上创建) -
分支策略 :使用
master分支作为主分支,dev分支作为开发集成分支
2.2 将协作者添加到项目
在真正的团队协作中,项目管理员需要将团队成员添加为项目的协作者:
-
进入Gitee项目页面,点击「管理」->「成员管理」
-
添加仓库成员:输入协作者的Gitee用户名或邮箱
-
设置权限:通常设置为「开发者」权限(可以推送代码,但不能修改仓库设置)
-
生成邀请链接:或者通过生成邀请链接的方式让队友加入
三、 基于功能分支的协作实战
现代Git工作流的核心是功能分支(Feature Branch)工作流。每个新功能都在独立的分支上开发,完成后通过合并请求(Pull Request)集成到主分支。
3.1 场景设定
假设我们的项目需要开发两个新功能:
-
功能1:用户登录模块(由开发者A负责)
-
功能2:订单管理模块(由开发者B负责)
3.2 开发者A的工作流程
步骤1:克隆仓库并查看分支
liu@139-159-150-152:~$ git clone git@gitee.com:liu/git_teaching.git
Cloning into 'git_teaching'...
liu@139-159-150-152:~$ cd git_teaching
liu@139-159-150-152:~/git_teaching$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
步骤2:基于master创建功能分支
liu@139-159-150-152:~/git_teaching$ git checkout -b feature-user-login
Switched to a new branch 'feature-user-login'
步骤3:在功能分支上开发
# 创建用户登录相关的文件
liu@139-159-150-152:~/git_teaching$ mkdir src
liu@139-159-150-152:~/git_teaching$ echo "用户登录功能实现" > src/login.py
liu@139-159-150-152:~/git_teaching$ git add src/login.py
liu@139-159-150-152:~/git_teaching$ git commit -m "feat: 实现用户登录基础功能"
[feature-user-login 29f8a7b] feat: 实现用户登录基础功能
1 file changed, 1 insertion(+)
create mode 100644 src/login.py
步骤4:推送功能分支到远程
liu@139-159-150-152:~/git_teaching$ git push origin feature-user-login
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 328 bytes | 328.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:liu/git_teaching.git
* [new branch] feature-user-login -> feature-user-login
3.3 开发者B的工作流程
步骤1:克隆仓库(如果尚未克隆)
# 在Windows PowerShell中
PS D:\> git clone git@gitee.com:liu/git_teaching.git
PS D:\> cd git_teaching
步骤2:获取最新分支信息并创建自己的功能分支
PS D:\git_teaching> git fetch origin
PS D:\git_teaching> git checkout -b feature-order-management
Switched to a new branch 'feature-order-management'
步骤3:在功能分支上开发
PS D:\git_teaching> mkdir src
PS D:\git_teaching> echo "订单管理功能实现" > src/order.py
PS D:\git_teaching> git add src/order.py
PS D:\git_teaching> git commit -m "feat: 实现订单管理基础功能"
[feature-order-management e1233f1] feat: 实现订单管理基础功能
1 file changed, 1 insertion(+)
create mode 100644 src/order.py
步骤4:推送功能分支到远程
PS D:\git_teaching> git push origin feature-order-management
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 332 bytes | 332.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:liu/git_teaching.git
* [new branch] feature-order-management -> feature-order-management
3.4 查看远程仓库状态
此时登录Gitee,在项目页面的「分支」标签页中,可以看到两个功能分支都已经推送到远程:
分支列表:
- master (默认分支)
- feature-user-login (最新提交: 29f8a7b)
- feature-order-management (最新提交: e1233f1)
四、 代码审查与合并(Pull Request)
功能开发完成后,需要通过Pull Request(PR) 或 **Merge Request(MR)** 的方式进行代码审查和合并。这是保证代码质量的重要环节。
4.1 创建Pull Request
开发者A为登录功能创建PR:
-
在Gitee项目页面,点击「Pull Requests」->「新建Pull Request」
-
选择分支:
-
源分支:
feature-user-login -
目标分支:
master
-
-
填写PR信息:
-
标题:
feat: 添加用户登录功能 -
描述:详细说明本次提交的功能、修改内容、测试情况等
-
-
指定审查者:选择项目中的其他成员作为代码审查者
-
创建PR:点击「创建」按钮生成Pull Request
开发者B为订单功能创建PR:
同样的流程,创建从feature-order-management到master的Pull Request。
4.2 代码审查流程
审查者(可以是开发者B或其他团队成员)的审查过程:
-
查看代码变更:在PR页面查看所有修改的文件和代码差异
-
评论和建议:对具体代码行提出疑问或改进建议
-
测试验证:可以在本地 checkout 该分支进行测试
-
审批通过:如果代码符合要求,点击「通过」按钮
在本地测试功能分支
liu@139-159-150-152:~/git_teaching git fetch origin liu@139-159-150-152:~/git_teaching git checkout -b test-feature origin/feature-order-management
4.3 合并Pull Request
审查通过后,可以选择合并方式:
-
Merge合并:创建合并提交,保留完整历史(推荐)
-
Squash合并:将多个提交压缩成一个提交,保持历史整洁
-
Rebase合并:重新应用提交,生成线性历史
合并后,功能分支的代码就集成到了master分支中。
五、 处理协作中的冲突
冲突是多人协作中的常见情况,重要的是学会如何正确处理。
5.1 冲突场景模拟
假设开发者A和开发者B同时修改了同一个文件:
liu@139-159-150-152:~/git_teaching$ echo "项目描述 - 由开发者A更新" > README.md
liu@139-159-150-152:~/git_teaching$ git add README.md
liu@139-159-150-152:~/git_teaching$ git commit -m "docs: 更新项目描述"
liu@139-159-150-152:~/git_teaching$ git push origin feature-user-login
PS D:\git_teaching> echo "项目介绍 - 由开发者B更新" > README.md
PS D:\git_teaching> git add README.md
PS D:\git_teaching> git commit -m "docs: 更新项目介绍"
PS D:\git_teaching> git push origin feature-order-management
现在两个功能分支都对同一个文件进行了修改。
5.2 冲突的发现与解决
当开发者A先合并了他的PR后,开发者B在合并时就会遇到冲突:
在Gitee上合并时会直接显示冲突警告,需要手动解决。
在本地解决冲突的流程:
# 1. 先拉取最新的master分支代码
PS D:\git_teaching> git checkout master
PS D:\git_teaching> git pull origin master
# 2. 切换回功能分支并合并master
PS D:\git_teaching> git checkout feature-order-management
PS D:\git_teaching> git merge master
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
# 3. 查看冲突文件
PS D:\git_teaching> cat README.md
<<<<<<< HEAD
项目介绍 - 由开发者B更新
=======
项目描述 - 由开发者A更新
>>>>>>> master
# 4. 手动解决冲突(编辑文件,保留需要的内容)
PS D:\git_teaching> vim README.md
# 修改为:项目描述和介绍 - 由开发者A和B共同更新
# 5. 标记冲突已解决并提交
PS D:\git_teaching> git add README.md
PS D:\git_teaching> git commit -m "fix: 解决README.md冲突"
# 6. 推送更新
PS D:\git_teaching> git push origin feature-order-management
5.3 冲突解决的最佳实践
-
频繁拉取更新:经常从主分支拉取更新,减少冲突范围
-
小步提交:每次提交的变更尽量小,便于冲突解决
-
及时沟通:与队友沟通修改意图,避免重复劳动
-
使用合适的工具:IDE通常提供图形化的冲突解决工具
六、 高级协作技巧
6.1 使用git stash处理临时任务
当你正在开发一个功能时,突然需要处理紧急任务:
# 当前正在feature-user-login分支工作
liu@139-159-150-152:~/git_teaching$ echo "正在开发的功能..." >> src/login.py
# 突然需要修复紧急bug
liu@139-159-150-152:~/git_teaching$ git stash push -m "保存登录功能开发进度"
liu@139-159-150-152:~/git_teaching$ git status # 工作区变干净了
# 创建紧急修复分支
liu@139-159-150-152:~/git_teaching$ git checkout -b hotfix-critical-bug
# ...修复bug并提交...
# 回到功能分支恢复工作
liu@139-159-150-152:~/git_teaching$ git checkout feature-user-login
liu@139-159-150-152:~/git_teaching$ git stash pop
6.2 使用rebase保持历史整洁
在合并前使用rebase整理提交历史:
liu@139-159-150-152:~/git_teaching$ git checkout feature-user-login
liu@139-159-150-152:~/git_teaching$ git fetch origin
liu@139-159-150-152:~/git_teaching$ git rebase origin/master
# 如果有冲突,解决冲突后继续rebase
liu@139-159-150-152:~/git_teaching$ git rebase --continue
# 强制推送更新后的分支
liu@139-159-150-152:~/git_teaching$ git push origin feature-user-login --force
注意:强制推送会重写历史,只应在个人功能分支上使用。
6.3 分支保护策略
在Gitee中可以设置分支保护规则:
-
进入「管理」->「分支管理」
-
设置保护分支(如master)
-
配置规则:
-
禁止直接推送
-
要求Pull Request
-
需要代码审查
-
需要状态检查通过
-
七、 协作中的常见问题与解决方案
7.1 推送被拒绝(Push Rejected)
liu@139-159-150-152:~/git_teaching$ git push origin feature-user-login
To gitee.com:liu/git_teaching.git
! [rejected] feature-user-login -> feature-user-login (non-fast-forward)
error: failed to push some refs to 'git@gitee.com:liu/git_teaching.git'
解决方案:
# 先拉取远程更新
liu@139-159-150-152:~/git_teaching$ git pull origin feature-user-login
# 解决可能的冲突后再次推送
liu@139-159-150-152:~/git_teaching$ git push origin feature-user-login
7.2 分支追踪关系丢失
liu@139-159-150-152:~/git_teaching$ git branch -vv
feature-user-login 29f8a7b [origin/feature-user-login: gone] feat: 实现用户登录基础功能
解决方案:
liu@139-159-150-152:~/git_teaching$ git branch --set-upstream-to=origin/feature-user-login feature-user-login
7.3 清理远程已删除的分支
liu@139-159-150-152:~/git_teaching$ git fetch --prune origin
liu@139-159-150-152:~/git_teaching$ git branch -a
八、 总结
本章我们深入探讨了Git多人协作开发的完整流程:
-
协作基础:理解了功能分支工作流和Pull Request机制
-
实战演练:通过完整案例演示了从分支创建到代码合并的全过程
-
冲突处理:学会了如何预防、发现和解决代码冲突
-
高级技巧:掌握了stash、rebase等提高协作效率的工具
-
问题解决:了解了常见协作问题的处理方法
多人协作就像音乐合奏,需要每个参与者都遵循相同的节奏和规则。通过规范的Git工作流、清晰的代码审查和有效的沟通,团队可以高效地协作开发复杂的软件项目。
在下一篇中,我们将进入企业级开发的主题,学习标准的Git分支模型和DevOps实践,了解如何将Git集成到完整的软件开发生命周期中。