功能分支工作流实战

创建各自的功能分支

们来按照真实的网站开发过程体验一下分支的使用和合并过程:
(1)开发一个OA系统,俩人,张三和李四
张三:/f/development/eclipse/eclipse-workspace/oa-parent 李四:/f/development/workspace/oa-parent
(2)张三从master分支上,拉一个新的feature分支,叫做feature/001,然后在分支上做一些开发,开发新功能;李四从master分支上,拉一个新的feature分支,叫做feature/002,然后在分支上做一些开发
拉一个分支下来:git checkout -b feature/001,就会从当前分支拉一个分支出来
notion image
比如你现在在master分支上,然后你执行了git checkout -b feature/001这个命令,此时会创建一个新的分支对应的指针,feature/001,指向了master当前指向的那个commit object,同时如果切换到了feature/001分支,HEAD会指向feature/001
git为什么要这么玩儿?
git不会说,每次创建一个分支,就直接拷贝一份代码,效率太低了
在git中,整个所有的版本和文件只存储一次,只存储一份,提交历史,commit树,只有一份
每个commit object就代表了这个项目在当前时刻一个完整的快照版本,代表了一份完整的代码了
所以创建分支,就是创建一个轻量级的指针而已,指向了某个commit object,你的当前所处的分支指向哪个commit object,就是指向了哪个版本的代码,你的工作区中的代码就是那个版本的代码
李四:git checkout -b feature/002
张三进行开发提交了两次,oa-auth里面加入新功能 李四进行开发提交了一次,oa-doc里面加入新功能

hotfix

这个时候张三接到一个通知,有一个bug,需要进行hotfix。这个时候我们需要切换到master分支上,拉一个hotfix分支,拉bugfix/001。在hotfix分支上修复bug,然后测试和验证一下,合并到master分支,用master分支代码部署,解决线上bug。删除bugfix/001分支
张三:git checkout master,git checkout -b bugfix/001,修改bug,提交,再将bugfix/001分支合并到master分支
如果你要git checkout master,首先需要将当前分支上修改的代码全部git add然后git commit,才能切换分支
合并分支:切换到master分支,然后执行git merge bugfix/001
notion image
这里执行的是一种merge,叫做fast-forward,快进式merge
我们此时就不需要bugfix/001分支了?为啥,因为master分支就指向了那个commit了,要bugfix/001分支还有何用?
给删除掉bugfix/001分支:git branch -d bugfix/001
张三继续切换回feature/001分支,继续开发工作,开发完之后合并到master,删除feature/001分支
notion image
李四同时一直在开发feature/002分支,完成之后合并到master,删除feature/002分支
 
接着我们从Git分支的角度来说一下上面整个实验步骤和内幕原理:
首先,假设我们的master分支已经走过了几个commit了,当前master指向的是最新的一个commit。比如有三个commit object,c0,c1,c2,而master指向的就是c2,HEAD指向master。
此时我们需要开发一个新的功能,可以从master分支拉一个feature/iss53分支
git checkout -b feature/iss53,这个命令是在创建分支的同时也切换到这个分支上去,相当于是git branch feature/iss53,git checkout feature/iss53
此时master继续指向c2,但是多了一个feature/iss53指针,指向c2,同时HEAD切换为指向feature/iss53了。
接着我们就可以在feature/iss53分支上做一些开发了,主要是为了新功能写代码,而且一般每天都会执行一次提交,保证工作内容不会丢失,这个过程之后,c2 commit之后会长出来一个新的c3 commit,然后feature/iss53指向了这个c3,HEAD继续指向feature/iss53。
此时接到一个通知,需要解决一个线上的bug。此时就需要切换到master分支,然后拉一个新的hotfix分支。但是在切换到master分支之前,是需要先提交你的feature/iss53的所有代码的,否则是不允许切换分支的。
git checkout master git checkout -b hotfix/bug61
一旦切换到master分支,工作区的所有代码会给git还原为master指针指向的那个commit object的所有快照,git会负责对代码文件进行新增、修改或者删除,彻底还原到那个快照版本。
接着拉取并且切换到hotfix/bug61之后,我们就可以基于master的代码来进行bug修复了,修改代码,解决bug,进行测试,然后在hotfix/bug61上可以提交代码。这里注意一点,可以让hotfix/bug61分支的代码和feature/iss53分支的代码,都对同一行进行不同的修改,为了后面的合并冲突解决进行准备。
这个时候,master继续指向c2,feature/iss53指向c3,然后从c2长出来一个新的c4 commit object,hotfix/bug61指向c4。也就是说,从c2之后,分叉长出来两个commit object,c3和c4。
接着,对hotfix/bug61的代码需要进行测试,然后测试通过之后,就可以将hotfix/bug61分支合并到master分支,准备上线了。
git checkout master git merge hotfix/bug61
这次merge被称之为fast-forward,快进式的merge,为啥呢?因为看一下此时的commit树,master指针只要直接移动到指向c4,就可以完成本次合并了,这就是fast-forward。但是此时HEAD就是指向master的。
此时就可以用master代码来部署解决bug了。
同时,我们已经不再需要hotfix/bug61这个分支了,因为已经合并到master分支了,此时可以删除hotfix/bug61这个分支。
git branch -d hotfix
然后切换回feature/iss53分支,继续你的新功能的开发:git checkout feature/iss53
完成一些代码,然后最终commit一次,结束feature/iss53的代码开发,同时基于这个分支的代码完成测试。此时会从c3长出来一个c5,feature/iss53指向c5,而且HEAD指向feature/iss53。
接着就要将feature/iss53分支合并到master分支了,完成功能的合并
git checkout master git merge feature/iss53
此时,因为master指向的commit,是不能直接移动到feature/iss53指向的commit的,因此需要执行一个3-way merge。此时会创建一个新的commit object,叫做c6,然后父commit是两个,c4和c5。此时,master会指向最新的c6,feature/iss53继续指向c5,同时HEAD指向master。
接着就可以删除feature/iss53分支了,git branch -d feature/iss53 但是合并的时候有可能会出现冲突,就是可能两个分支对同一行代码的修改不一样,此时会提示有CONFLICT,然后automatic merge failed,需要我们去解决冲突。
此时,我们首先需要执行git status命令,来看一下哪些代码中出现了冲突,会提示你unmerged paths,里面有both modified的一些文件。
接着进入那些文件,开始解决冲突
会提示你HEAD中的某一行是什么样子的,然后要合并进HEAD的其他分支的这一行是什么样的。此时你需要自己决定该如何修复冲突。
修复冲突之后,需要执行git add命令,将这些修改后的文件放入暂存区,接着执行git commit命令,来提交冲突解决的修改。此时就会继续创建一个新的commit出来,c6,它包含的就是master和feature/iss53合并以后,同时解决了冲突以后的快照。c6的父节点也是c4和c5。