Welcome to 9ilk's Code World

(๑•́ ₃ •̀๑) 个人主页: 9ilk
(๑•́ ₃ •̀๑) 文章专栏: Git
前面我们学习了Git的所有本地仓库的相关操作:git基本操作,分支理解,版本回退,冲突解决等等。同时我们还理解了远端仓库在开发的作用以及相关操作push和pull。但更重要的是Git是一把团队开发的利器,我们应该见见实际中利用Git进行多人开发的场景。
🏠 多人开发场景一
目标:远程仓库master分支下file.txt文件新增代码"aaa" "bbb"。
实现 :开发者1 新增**"aaa",** 开发者2 新增**"bbb"**。
条件 :在一个分支下协作完成。
我们知道master往往是作为稳定的分支,一般开发我们是新建一个开发分支dev来进行开发,稳定开发没有问题之后再合并到master分支上,因此我们可以在远程仓库上新建开发分支dev:

模拟两个开发者
说明:我们以Linux云服务器作为开发者1,Windows作为开发者2。
(1)开发者1
对于开发者1,目前的状态如下:

此时开发者1是看不到远端刚新建的开发分支的:
bash
git branch -r //查看远程分支

我们需要对远端仓库进行拉取:
bash
git pull //拉取
git branch -a //同时打印本地和远程分支

此时开发者1的状态:

补充细节 :对于git push + 远程仓库 远程分支,此时是不需要与远程仓库建立远程连接的 ;git clone的时候,Git会自动为本地仓库的master分支和远程仓库的master分支建立连接,因此我们能直接使用git push命令将本地修改推送到远端,而不用指明远程仓库和远程分支。
(2)开发者2
Windows本地选取目录作为本地仓库进行git clone远端仓库:

开发者2此时的状态:

开发者1dev分支新增
我们可以在本地也新建分支来开发**,并且和远程的开发分支建立连接**:
bash
git checkout -b dev1 origin/dev1 //本地新建dev1分支+切换到该分支+追踪远端dev1分支
此时对于dev1分支向远端推送时,可以直接使用git push到远端的dev1分支,而不用指明仓库,我们可以使用git branch -vv 命令查看本地分支和远端分支的关系:

开发者1对file.txt文件新增"aaa"并推送到远端:
bash
vim file.txt //新增aaa
git add file.txt
git commit -m "modify aaa file.txt"
git push
我们到远端仓库的dev1分支上就能看到file.txt新增aaa:

开发者2dev分支新增
同样我们也需要在开发者2本地仓库新建分支进行开发:

与开发者1不同,我们新建分支时并没有与远程仓库建立连接,我们可以使用git branch --set-upstream-to=【远程分支】 【本地分支】 来追踪远端仓库的分支

开发者2对file.txt新增"bbb"并提交:

由于开发者1之前已经对远端提交了修改,因此冲突是少不了的,此时我们应该git pull拉取远端仓库内容,并手动解决冲突后提交:

开发分支dev合并到master
(1) 方式一:本地的master分支合并本地dev分支,再推送本地master分支到远端的master
(2) 方式二:在远端仓库提交Pull Request 由管理员进行合并
说明:我们这里演示方式一。
我们之前讲过master是作为我们线上发布的一个稳定分支,所以我们不能直接让master合并dev,因为可能产生冲突,我们最好是先让dev合并master,有冲突在dev上解决,解决完再让master合并dev。
但在进行dev合并master操作之前,我们最好养成一个好习惯,即先从远端仓库拉取一下,保证本地dev是最新的:

master pull:

dev合并master:

确认无冲突之后,master合并dev分支并推送到远程master分支:
我们可以到远程仓库进行查看:

此时dev1分支的开发任务到这里就已经结束了,我们可以在本地和远端对其进行删除。
总结
在同一分支下进行多人协作的工作模式通常是这样:
-
首先,可以试图用git push 远程仓库 远程分支 推送自己的修改。
-
如果推送失败,则因为远程分支比你的本地更新,需要先使用git pull试图合并。
-
如果合并存在冲突,则解决冲突,并在本地提交。
-
没有冲突或解决完冲突之后,再用git push 远程仓库 远程分支 推送即可。
-
功能开发完毕,将分支merge进master,最后删除分支。
🏠 多人开发场景二
目标:远程master分支下新增function1和function2文件,代表两个功能。
实现 :由开发者1 新增function1 ,开发者2 新增function2。
条件 :在不同分支下协作完成。
我们要实现的场景概括起来就是:两个开发者各自一个分支,各自开发各自功能,在不同分支下进行协作。
既然要创建分支,我们知道创建分支有两种方式:
- 方式一:在远程新建分支,在本地进行push和拉取。
- 方式二:在本地新建分支,完成开发之后再push到远程仓库。
说明: 对于这两种方式,更推荐第一种 ,因为我们远程创建的话,基于master创建新分支,而此时远程仓库的master分支是目前最新最稳定的 ;而如果是方式二的话,你本地的master分支不一定是最新的,功能分支和master分支合并之前,本地master还需要pull拉取远程仓库,因此操作比较冗杂。
**注:**之前方式一我们已经演示过了,我们本次演示下方式二。
开发者1开发
假设开发者1需要新增function1功能,此时我们可以在本地新建分支进行开发,开发完成之后利用Git三板斧提交到远程仓库:

由于我们是在本地新建的开发分支,在远端是没有该分支与我们进行连接的 !我们可以使用git push 远程仓库 远程分支 来直接推送到远端:
注 : 我们之前进行与远程仓库连接跟踪,使用的是git checkout -b 新分支 远程仓库/远程分支(新建分支的场景) 和**git push --set-upstream 远程仓库 远程分支(远程中已经存在对应的分支),**我们现在的场景中并不是新建分支而且远程也没有对应分支。

此时我们在远程仓库应该看到除了master分支之外,存在新分支feature1:

开发者2开发

上一个开发场景中,我们对于file.txt最新应该是新增了aaa bbb内容的,对于开发者2来说,master还不是最新的!我们首先应该先git pull一下,这也是一个好习惯
bash
git pull
拉取完之后开发者2就可以进行正式开发了, 同样我们也是新建本地分支开发,开发完成之后进行三板斧操作直接推送到远端:

注意 : 此时本地的feature2是并没有对远程的feature2分支进行追踪管理的,即没有进行连接

此时开发者1和开发者2状态如下:

此时,在本地开发者1和开发者2互相看不到各自的文档,并且推送各自的分支时,并没有任何冲突,互不影响!
协作开发
由上可知,开发者1和开发者2目前是互不影响的,但是否能由开发者1暂时承担开发者2的开发任务呢? 答案是可以的。
开发者1本地是没有远程feature2分支的,因此我们应该首先从远端拉取内容:

Q:为什么这里可以直接git pull 而不需要和远程的feature2先建立连接?
拉取某个特定分支下的内容是需要先建立连接的,才能直接使用git pull命令。
拉取远程仓库中的内容,即拉取分支是不需要建立连接的。
注意 :如果不先拉取,在本地就无法查看到远程feature2分支的信息,也就无法建立来连接,进行追踪管理!
拉取完远程仓库之后,我们就可以继续进行开发了。但是开发者1本地是没有feature2分支的,我们首先应该先建立本地feature2分支并进行追踪,然后进行开发:

恢复开发
由于开发者1之前帮我们开发了一部分,此时开发者2需要在本地进行同步,即从远端进行拉取,但之前开发者之前并没有与远程feature2分支建立连接,而是直接推送到远程仓库指定分支,因此我们可以采用以下两种方式进行拉取:
bash
//方式一:本地先与远程建立连接再直接git pull
git branch --set-upstream-to=origin/feature2 feature2
git pull
//方式二:pull时指明远程仓库和远程分支
git pull <remote> <branch>
即git pull origin feature2

开发者2开发完之后就可以执行三板斧,此时是已经建立连接的,我们可以直接git push:

打开远程仓库,我们就能发现feature2分支下的function2功能:

功能合并
(1) 通过PullRequest将feature2合并到master
之前我们讲解到合并分支有两种方式:1. 在本地 dev先合并master-> 有冲突解决冲突,无冲突则master合并dev,push本地master到远端仓库的master 2. 使用PullRequest在远程合并分支。本次我们讲解第二种方式。
填写PullRequest:

一般在远程仓库合并分支要经历一下流程:

当审查发现无问题之后就会显示可自动合并,我们就能在master分支下查询到开发者2开发的功能:

(2) 本地feature1分支合并master再push到远程
我们先分析一下目前的状态:

feature1要想合并到master,此时由于开发者1和开发者2是各自私有一个功能,因此不会产生冲突。如果有冲突,该怎么解决呢?
我们一个较好的方案是 : 先让feature1在本地合并一下master分支,有冲突就在本地进行解决,然后在push到远程的feature1分支,最后再提交PullRequest在远程进行合并。
同样的,在merge之前,我们最好先pull一下 ,保证本地master是最新的:
本地将master合并到feature1:
将本地推送到远端:

(3) 通过PullRequest将feature1合并到master
我们已经完成了前两步,剩下的就是在远端提交PR将feature1合并到master:

此时在远程仓库我们应该看到master分支下具有func1和func2两个模块:

注意: 到这里feature1和feature2分支的任务已经完成了, 我们可以对其进行删除

总结
当多人各自开发一个功能模块时 :
-
各自可以在远程或本地新建分支进行功能开发
-
开发完成之后可以在远端提交PR进行合并
-
为了防止冲突,也可以在本地进行合并master,解决完冲突之后push到远端再提交PR
🏠 远程分支删除后,本地git branch -a依然能看到的解决方法
我们之前在远端已经删除了两个功能分支,但是当我们使用git branch -a选项查看时还能查看:

我们可以使用git remote show origin 来查看更详细的远程分支信息:

我们可以看到对于在远程已经删除的分支,它提示我们可以使用git remote prune进行移除
