GIT的分支管理
一 分支介绍
如果把Git比喻为一条小河,master分支是小河的主干/主分支,其他分支就是这条小河的支流,可以把所有分支合并到一起形成一条大河,滚滚奔向大海……
Git本质上只是一棵巨大的文件树,分支指的是树的一个分叉,我们可以对分支进行合并。
那么分支在实际开发中有什么用处呢?
如果你准备开发一个新功能,需要两周才能完成,第一周你写了50%的代码,此时如果立刻提交,由于代码还没写完,而不完整的代码库会导致别人不能干活了。但如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
分支是Git的杀手级特征,而且Git鼓励在工作流程中频繁使用分支与合并,哪怕一天之内进行许多次都没有关系。因为Git分支非常轻量级,不像其他的版本控制,创建分支意味着要把项目完整的拷贝一份,而Git创建分支是在瞬间完成的,而与你工程的复杂程度无关。
Git理论扩展阅读:https://www.bookstack.cn/read/the-core-conception-of-git/0.md
二 创建分支与合并分支
分支可以被理解为一条时间线,这一条时间线上串着一个个节点,每个节点都是一次提交记录/版本。
git默认只有一条时间线or分支,该时间线or分支称之为主分支,即master分支,文件.git/refs/heads/master 内存放着指向master分支最新版本的指针,如果下所示红色块即master指针,指向master分支
每次提交,master
分支都会向前移动一步,master指针指向最新提交的一个版本,这样,随着你不断提交,master
分支的线也越来越长,如下
如果我们有多个分支,那么GIT如何实现在多个分支之间来回切换的呢,.git
文件夹下的HEAD
文件负责存放当前所在的分支ref: refs/heads/<分支名称>
,切换分支就是修改HEAD文件中的内容为对应分支,并将工作区的文件恢复至对应分支的内容,所以严格来说HEAD
不是指向提交,而是指向当前所在的分支,比如master,master
才是指向提交的,一开始的时候,master
分支是一条线,Git用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点:
当我们创建并切换到一个新的分支,例如dev
时
- 1 、Git会新建一个指针叫
dev
,指向master
相同的提交 - 2、然后再把
HEAD
指向dev
,就表示当前分支在dev
上 - ps:Git创建一个分支很快,因为除了增加一个
dev
指针,改改HEAD
的指向,工作区的文件都没有任何变化!
如果HEAD指向dev,那么代表当前分支在dev上,这意味着接下来对工作的修改和提交都是针对dev分支了,如果master是小河的主干,那么dev就是这条河的支流,主干的水被引入了支流.
比如提交一次后,dev指针往后移动一步,而master指针不变
当在master
分支合并dev
分支时,因为他们在一条线上,这种单线的历史分支不存在任何需要解决的分歧,所以只需要master
指针指向dev
分支的最新一次提交即可,所以非常快。
所以你看,git不仅创建分支快,合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支,甚至都看不出来添加过dev分支,毁尸灭迹了
实操
-
1、在当前分支下创建子分支并切换
-
2、直接切换到已有分支
-
3、查看当前分支
-
4、切换到dev分支下修改并提交记录/版本
如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward),上述合并git merge dev用的就是Fast-forward快进模式,毫无疑问不是每次合并都能采用
Fast-forward
,我们将在第四小节介绍。合并完成后,就可以放心地删除dev分支了
因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。
-
5、switch
三 分支管理策略
Fast-forward快进模式下合并的结果如下图所示
该模式下,删除分支dev后,查看版本日志根本看不到做过合并
如果想在删掉分支后,也能在版本日志里看到做过合并操作,需要在git merge时强制禁用Fast forward
模式,并且提交一个的版本
如果merge时使用Fast forward
模式
如果mere时禁用Fast forward
模式,会提交一个新的版本
删除分支dev后查看
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
小结
Git分支十分强大,在团队开发中应该充分应用。
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。
四 解决冲突
承接第二小节:如果顺着一个分支走下去可以到达另一个分支,中间无分叉的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)
但如果合并版本时有冲突问题,便不可用快进模式,当分支出现分叉时,就有可能出现冲突,而这时Git就会要求你去解决冲突,比如像下面的历史
分支和dev
分支不在一条线上,即v7
不是v5
的直接祖先,Git 不得不进行一些额外处理。就此例而言,Git 会用两个分支的末端(v7
和 v5
)以及它们的共同祖先(v3
)进行一次简单的三方合并计算。合并之后会生成一个和并提交v8
:
注意:合并提交有两个祖先(v7
和v5
)。
五 Bug分支
开发软件的过程中,软件出现bug是非常正常的一件事,当我们在开发过程中遇到了bug,可以在出现bug的分支上创建并切换到一个临时的子分支,可以称之为bug分支,然后在该临时子分支上修复bug并提交,随后切回出现bug的分支上合并bug分支修复的内容,然后删掉临时的bug分支即可。
具体场景。。。
此时我们正在dev分支上进行开发,开发工作只进行了一半,还需要几天才能搞定,此时领导交给你一个代号487的bug修复的任务,要求在两个小时内修复完成,此时你必须放下手头dev分支的开发任务去修复bug,此时dev分支未完成的工作肯定是需要保存下来以便bug修复完成后重新继续开发下去的,如果把dev分支未完成的开发内容直接提交一个版本肯定是可以的,但我们通常是在开发完成一个任务后才去提交一个版本,你只写一行代码就提交一个版本,那岂不是非常乱,所以我们的需求是想在不提交新版本的前提下把开发的内容暂存下来,这就用到了git stash命令保存和恢复工作进度
前提:必须是处于git下的文件,从来未曾add到git的文件无法使用。
快速掌握
详解如下:
示例
1、在dev分支正在进行开发任务,开发到一半,遇到了要在两小时修复代号487的bug,先保存工作现场,将工作区和暂存区还原到修改之前
2、切换到出现bug的分支下(假设此时为master分支),创建子分支,在子分支上修改bug
3、修复完成后,切换到master
分支,并完成合并,最后删除issue-487
分支:
4、重新切回dev分支,把stash的内容拿回来,继续干活
思考:
dev分支当初就是从master分支分出来的,所以dev与master的源头一样,如果说master上的某个节点有bug,并且该节点处于dev分支之前,那么dev分支上肯定也有该bug,那如何修复呢?重复上述操作肯定可以,但重复操作毕竟不是那么聪明,我们其实可以这么做
用git cherry-pick
,我们就不需要在dev分支上手动再把修bug的过程重复一遍。
有些聪明的童鞋会想了,既然可以在master分支上修复bug后,在dev分支上可以“重放”这个修复过程,那么直接在dev分支上修复bug,然后在master分支上“重放”行不行?当然可以,不过你仍然需要git stash
命令保存现场,才能从dev分支切换到master分支。
六 Feature分支
master
分支应该是非常稳定的,也就是仅用来发布新版本,为了防止搞乱,平时不能在上面干活,我们通常在dev分支上开发代码,而开发的过程中肯定涉及到五花八门各种各样的功能要添加到软件中,为了不让新功能的代码搞乱dev,我们同样应该在dev上开辟子分支,称之为feature分支,在feature上开发完毕后,再切回dev分支进行合并,然后删除掉featrue分支即可
现在,你终于接到了一个新任务:开发代号为绿帽子的新功能,该功能计划用于为全世界的男人戴上绿帽子。
于是你准备开始
切回dev分支,准备合并
一切顺利的话,feature分支和bug分支都是类似的处理方式,合并,然后删除即可。
但是!
就在此时,接到上级命令,因经费不足,新功能必须取消!
虽然白干了,但是这个包含机密资料的分支还是必须就地销毁: