如何使用 Git 进行多人协作开发(全流程图解)
如何使用 Git 进行多人协作开发(全流程图解)
在软件开发中,多人协作是一项必不可少的任务。而Git作为目前最受欢迎的分布式版本控制工具,提供了强大的功能和灵活的工作流程,使得多人协作开发变得更加高效。本文将带你实践如何正确使用Git进行多人协作开发,重点讲解Feature Branching分支管理策略以及单分支和多分支协作开发的具体流程。
分支管理策略
Git分支策略允许开发人员在一个项目上进行协作,同时跟踪更改并维护多个版本的代码库。主流的分支管理策略有Trunk-Based Development、Feature Branching、Git Flow等等,本文将基于较为简单的Feature Branching分支管理策略展开。虽然分支管理策略多种多样,但最好的策略一定是与你的团队特征和项目需求相匹配的。
1.什么是Feature Branching?
在实际开发中,master分支非常强调环境的稳定性。因此当我们要开发新的功能或者特性时,需要从master分支上拉取feature分支,这样开发者就能在feature分支上独立开发而不影响主分支。当完成开发后,需要提交pull request将feature分支合并回master分支中。 通过pull request,仓库中的其他成员能对即将 merge 的代码进行审核并提出建议,从而保证了安全可靠性。
2.Feature Branching如何工作?
- 创建feature分支:feature分支一定是从master分支上拉取的
- 在feature分支上完成开发:通常一个分支就对应着一个特定的功能
- 提交pull request:请求将分支合并回master分支
- 审查批准:其他开发人员如果对你的代码满意的话,就会同意将你的分支合并到master分支。通过代码审查,我们通常能在分支 merge 回主分支前发现错误
- 清理:完成开发后,应该及时将没用的feature分支删除,保持代码仓库的整洁
下面将结合具体的例子为大家逐步骤实践上面的流程,同时带大家体会多人在单分支上开发和在多分支上开发的区别
多人协作一:单分支
- 任务:开发者A和开发者B在同一分支feature下开发。开发者A在 README 中增加一行 aaa,开发者B在 README 中增加一行 bbb
1.准备工作
- 场景:开发者A在创建分支前就克隆过远程仓库,而开发者B则在创建分支后才克隆远程仓库
在实际开发中,如果要进行多人协作开发,首先需要将其他成员添加进来
2.创建分支
创建分支的方式有两种:
- 在远程仓库直接创建
- 在本地创建分支 xxx 后使用指令git push origin xxx在远端创建一个与本地 xxx 分支对应的 xxx 分支
- 在单分支场景中,我们首先采用方法一创建分支
使用指令git branch -r指令可以查看远程仓库中的所有分支,但是对于开发者A而言只能看到 master 分支
原因也不难理解,开发者A是在创建feature分支前克隆远程仓库的,因此当前是落后于远程仓库的最新版本。我们需要使用git pull指令来更新分支信息:
🎯[说明]:
git pull指令具有以下两个作用:
- 拉取远程分支中的最新提交,并自动合并 (需要建立追踪关系)
- 更新远程仓库的分支信息(不需要建立追踪关系)
如何理解建立追踪关系呢?git pull 指令的完整用法是git pull <远程主机名> <远程分支名>:<本地分支名>,当我们完整使用 git pull 指令时,不需要考虑建立追踪关系的问题,而当我们简写为git pull时,本地分支默认为当前的工作分支,远程分支为与之建立链接的远程分支。当我们clone远程仓库时其实自动建立了本地master分支与远程master分支的追踪关系——即链接,因此我们可以采用简写的方式。
📌[建议]:在开发前首先使用git pull指令,确保从最新版本开始开发
在windows上模拟开发者B:
3.在分支上开发
开发者A:
- 在本地创建feature分支,并与远端的origin/feature分支建立连接
- git checkout -b featureorigin/feature指令创建一个feature分支并切换到feature分支上,并建立远端 feature分支的追踪关系
- git branch -a指令用于显示本地和远端的所有分支
- git branch -vv指令显示本地分支与远端分支的追踪关系。可以看到此时本地的feature分支已经与远端的origin/feature分支建立了连接
- 在feature分支上完成开发,并提交到远端的origin/feature分支上
开发者B:
在本地创建feature分支,并与远端的origin/feature分支建立连接
当我们尝试push到远端仓库时发生了冲突,原因是远端仓库的版本比我们当前的版本高(因为开发者A完成了push操作),我们首先需要pull远端仓库的分支内容,解决完冲突后才能再次 add + commit + push
📌[建议]:在开发前首先使用git pull指令,确保从最新版本开始开发
- 因为我们已经建立了本地feature分支与远端feature分支的链接,所以可以直接使用git pull指令拉取
- 手动解决冲突,从当前版本和远程仓库中的版本选择一个
- 重新 add + commit + push。此时我们就可以顺利推送到远程仓库了
4.分支合并
合并分支也有两种方式:
- 提交pull request,通过代码审验后合并到 master 分支
- 在本地 master 分支上合并后再 push 到远端的 master 分支
事先声明,方法一是更被推荐的。出于教学的考虑,在单分支的版本中,先带大家用用方法二
前面提到,我们要保证主分支的稳定性,因此我们不能直接将feature分支合并到master分支上,因为在解决合并冲突的过程中,我们就有可能在无意中改出了更大的 BUG。正确的做法是先将master分支合并到feature分支上,解决冲突后并且确认没有 bug 后再合并到master分支上。先前有过master和feature分支的合并记录,再合并时就不会出现冲突(都是本地操作)
将本地的master分支提交到远端
5.清理
完成合并后,就可以将没用的feature分支删除。删除分支也有两种方式:
- 在远端和本地分别删除feature分支
- 在本地删除feature分支后推送到远端
这里先为大家呈现第一种删除方式:
- 远端删除feature分支
- 本地删除feature分支
- 此时我们使用git branch -r指令仍然能看到origin/feature,此时我们需要使用git pull --prune指令进行修剪
多人协作二:多分支
多人在单分支上协作开发时,经常需要解决冲突的问题;而使用多分支,各个开发者在各自的分支上独立开发,只需要在最后合并分支时解决冲突即可
- 任务:开发者A在feature-1分支下编写文件file1。开发者B在feature-2分支下编写文件file1、file2
1.创建分支
前面提到,创建分支的方式有两种:
- 在远程仓库直接创建
- 在本地创建分支 xxx 后使用指令git push origin xxx在远端创建一个与本地 xxx 分支对应的 xxx 分支
我们现在采用第二种方式创建分支:
开发者A:
- 在本地创建feature-1分支。此时在创建本地分支时,我们不能再指定与远程分支orgin/feature-1建立连接,因此此时远程仓库中并没有这个分支
执行git push origin feature-1,Git 会将本地的feature-1分支推送到origin远程仓库中的相应分支。如果远程仓库不存在名为feature-1的分支,则 git 会创建之;如果存在,则将修改合并到该分支上
使用git branch -vv指令就可以发现,本地的feature-1分支并没有与远端的feature-1分支建立追踪关系。
因此我们不能直接使用 git pull、git push 等缩写指令。解决方法 git 也已经提示我们了①使用完整的命令 ②建立远端分支与本地分支的追踪关系
采用方法②来解决问题
开发者B同理
此时远端已经多了两个分支:
2.在分支上开发
开发者A与开发者B各自在分支上完成开发,并提交到远程分支feature-1与feature-2
3. pull request
我们前面提到,合并分支也有两种方式:
- 提交pull request,通过代码审验后合并到master分支
- 在本地master分支上合并后再 push 到远端的master分支
这里我们就是采用 pull request 的方式合并分支
开发者A:
- 提交pull request。可自动合并说明没有遇到冲突
- 仓库的管理人员完成对你的审核通过、测试通过后,就可以合并到master分支中。在“文件”一栏中可以看到你的修改
开发者B:
- 提交pull request。不可自动合并说明遇到了冲突
- 我们不能在 master 分支上处理冲突。解决方式与之前类似,先将master分支合并到feature-2分支上,解决完冲突后再将feature-2分支合并到master分支上
- 切换到master分支上,首先git pull拉取最新版本的master分支代码!!
- 切换到feature-2分支上,合并master分支。遇到冲突,冲动解决冲突
- 冲突解决,并推送到远端仓库
- 此时再次发起pull request请求就不会遇到问题了
4.清理
前面提到,删除分支也有两种方式:
- 在远端和本地各自删除feature分支
- 在本地删除feature分支后推送到远端
现在我们演示第二种删除方式
- 删除远端分支:git push origin --delete xxx。
- 删除本地分支:git branch -D xxx