还记得 Git 系列第一篇 Git 自我介绍的话吗?其中有 Git 本身都赞同的三大特点git
cheap local branching, convenient staging areas, and multiple workflowsbash
轻量的本地分支, 方便的暂存,以及多工做流。其中由于有分支的存在,才构成了多工做流的特点,因此 Branch 不愧为 Git 的王牌特点。这篇博客,主要和你们一块儿学习一下轻若鸿毛,帅到炸裂的分支儿。微信
分支的概念,在我看来,分两个版本:学习
从使用场景上解释,是这么个概念spa
Git 的分支,就是开发过程当中,要选择的一条路,你能够选择和其余小伙伴一块儿走同一条路,也能够本身走一条路,路与路之间相互没有影响,做为路的主人,你也随时可让两条路合并。命令行
深刻一点的话,是这么个概念:3d
Git 的分支,其实本质上仅仅是指向提交对象的可变指针,这个可变指针,指向路的终点。同时,还有一个比较特别的 HEAD 指针,用于记录当前工做的位置,借用上面的例子,这个 HEAD 指针等于在路上走的你本身,你在哪,指针就在哪,你在哪一个分支,HEAD 指针就指向哪一个分支的指针。 指针
实际上,当咱们使用 Git 的时候,咱们就使用了分支,由于 Git 的默认分支名字是 master,若是你有心的话,会发现执行 git init
后,命令行的输出头部已经默认在 master 分支了。 可是这个时候,还并未建立 master 分支,只有当有一个提交的时候,才会建立 master 分支。缘由在于,分支的指针要指向提交的呀,忽然明白了,当初看 Android Studio 的教程,为何每一个都让有一个初步提交了呢。code
无图无真相,不信的看下面:cdn
有关分支的命令很少,无非是换着花样的增删改查,掌握好如下基本的命令,之后就能够在 Branch 的草原上策马奔腾潇潇洒洒啦
git branch <name>
复制代码
这个命令看起来,彷佛简单到你只须要想个分支的名字就行了。
可是在建立分支的时候,要想下,是否要从当前分支的内容基础上去开辟一条新分支。
三个命令,让你想看什么分支就看什么分支,就是这么方便
git branch //查看本地分支
git branch -r //查看远程分支
git branch -a //查看本地和远程的全部分支
复制代码
当本地分支删除后,推进到远程仓库后,远程仓库并不能自动删除远程分支(缘由,下回分解)。因此,分支的彻底删除是分两个部分的,一个是本地,一个是远程。
本地删除操做须要加上 -d
或者 -D
参数,参数的名称来自英语 delete
的缩写,Remember it so easy!
二者的区别在于-D
比-d
要粗暴一点。当被删除分支有新内容没有被合并的时候,使用-D
,会直接删除, 使用-d
,会提示该分支有新内容没有被合并,不执行删除。删除需谨慎,建议非特殊状况下,使用温柔的-d
要好一点,以避免小手一抖,眼泪长流。
git branch -d <name>
git branch -D <name> //强制删除
复制代码
删除远程分支须要 push 操做。
git push origin :<name>
复制代码
其实,这是个伪命题。
可是有不少人,包括我,都有过对分支名称不满意想该修改一下的想法,因此,就有了这个伪命题的存在。
事实上,分支不存在重命名,没有 rename 的这个命令。若是你起的名字不满意,想从新起的话,那只要建立一个和要修改分支内容同样的分支,起上你喜欢的名字,而后再把以前的给删掉。
这个检出分支的“检出”二字,算是个关于 Git 分支的专业术语了,你能够理解为切换当前分支。
本质上, checkout 操做是移动 HEAD 指针,将 HEAD 指针指向要切换的分支的指针处。
使用场景有两个:
git checkout <name>
复制代码
建立一个新分支,并切换到新分支,这个一步到位的话须要 -b
参数。
以当前分支为基础,建立一个新分支
git checkout -b <branch name>
复制代码
以指定的某一个提交,建立一个新分支
git checkout -b <branch name> <SHA1>
复制代码
以上,是分支的增删改查独立操做,可是 Git 创造这个分支,并不仅是为了让它们自个儿和自个儿玩的,还须要它们之间的相互协做和配合。 就像写项目的时候,分好开发任务,你和你的小伙伴新建了两个分支,你写你的 Anglela,他写他的 baby,到开发完成以后,确定要合在一块儿,才能成就 Anglelababy。合的这个动做,就涉及到了分支合并的概念。
分支合并使用到的命令是
git merge <branch name>
复制代码
分支合并相对分支的其余操做,是相对要复杂一点的,怎么说也是多分支操做,至少要对得起它一听就比较高端的名字吧,因而我决定把分支的合并做为一个大标题。
分支的合并是很是智能的,目前有两种模式,两种模式的选择,不须要咱们参与,而是 Git 根据分支状况不一样,自行判断选择的。在我使用 Git 的过程当中,执行分支合并,有时须要输入提交信息,有时不须要,做为小白的我懵的不知因此然,后来才知道是由于合并模式的问题。
两种模式是:
如图,有两个分支,master 分支和 feature 分支。当这两个分支处于上面的关系时,当进行合并操做时,就会出现 fast-forward。
缘由是;因为当前 master 分支所指向的提交是 feature 分支的直接上游,因此 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,若是顺着一个分支走下去可以到达另外一个分支,那么 Git 在合并二者的时候,只会简单的将指针向前推动(指针右移),由于这种状况下的合并操做没有须要解决的分歧——这就叫作 “快进(fast-forward)”。
合并后的分支指针位置以下:
这个合并方式,是为补充 fast-forward 而出现的,由于你知道,在项目开发过程当中,不少人开发的状况下,出现 fast-forward 的状况并非不少,不少是相似下面这种。提交历史是分叉的,没法知足执行 fast-forward 的条件:
由于,master 分支所在提交并非 feature 分支所在提交的直接祖先,Git 不得不作一些额外的工做。 出现这种状况的时候,Git 会使用两个分支的末端所指的快照(C4 和 C5)以及这两个分支的工做祖先(C3),作一个简单的三方合并,生成一个新的提交(C6)。
提及来就是一堆理论,我本身都记不住,找个例子演示一下:
//建立一个文件夹,并初始化 Git
mkdir GitDemo
git init
//初次提交,建立 master 分支
touch master.txt
git add.
git commit -m '添加master文件'
//从master分支末尾,建立并切换 featureA 分支,并建立一个提交
git checkout -b featureA
touch A.txt
git add.
git commit -m '添加A文件'
//从master分支末尾,建立并切换 featureB 分支,并建立一个提交
git checkout master
git checkout -b featureB
touch B.txt
git add.
git commit -m '添加B文件'
//切换 master 分支
git checkout master
//master 合并 featureA 分支
git merge featureA
//master 合并featureA 后再合并 featureB 分支
git merge featureB
复制代码
博主不想给你说话,并向你投掷了一大串命令,快去敲敲看啊,会看到两种合并模式的!
master 分支合并 featureA 时,是快进式合并:
master 分支合并 featureA 后, 再合并 featureB 时,已经不知足快进式条件了,此时合并会触发一个三方合并,产生一个新的提交。因此,执行合并命令,会跳到下面的页面,让咱们编辑这个新提交的提交信息,默认提交信息是“Merge branch 'branch name'”. 按 i
编辑提交信息, :wq!
保存并退出页面。
合并成功后的提示信息:
画出上面小例子的分支合并,示意图,以下:
有人在的地方就有江湖,有分支在的地方,就有冲突。有时候合并操做不会如此顺利。 若是你在两个不一样的分支中,对同一个文件的同一个部分进行了不一样的修改,Git 就无法干净的合并它们,因而就会发生冲突。
以下,分别在 master 和 featureA ,在 master.txt 文件第一行添加一句话,而后两个分支合并,就会发生冲突。
冲突提示信息中,指明冲突文件为 master.txt。同时,也能够经过 git status
命令,查看冲突的详细信息
须要说明的是,若是遇到冲突的话,git 就没法自动合并了,接下来要靠咱们本身手动解决冲突,方法是:
git add
操做先知道一下思路,有个简单的概念在脑子里,接下来,一步一步仔细看~
冲突文件 master.txt 以下,git 虽然没法解决冲突, 可是已经帮咱们帮到最后了,使用简单的三个符号,标明了冲突的地方,以及冲突的两个分支在该地方发生冲突内容。
符号 | 意义 |
---|---|
======= | 分隔符 |
<<<<<<< HEAD 至 ======= | master 分支中该地方的内容 |
======= 至 >>>>>>> featureA | featureA 分支中该地方为内容 |
接下来编辑 master.txt 文件,完成合并,确认以后,把 git 冲突标识符号给删除掉便可。
现实中,不免有些时候,你会有后悔的念头。例如天天我迟到的时候,都会后悔为何第一遍闹钟响的时候没有起床,可是这个世界,没有后悔路能够走,我只能努力作到明天早起。
可是,Git 中有!由于神奇的 reset 和 revert 命令~,两个命令均可以达到回滚的效果,二者之间的区别之后会专门说,这里咱们使用 reset 。
提早声明:回滚以前,不要忘记作好备份,有备无患呐。
肯定回滚到哪一个提交,找到该提交的 commit id,执行如下命令,就行了
git reset --hard commit id
复制代码
依旧是个伪命题。远程分支不存在什么回滚,要想达到回滚的效果,就是删除以前的远程分支,而后把本地回滚好的本地分支,push 到远程。
git reset --hard commit id //本地分支回滚
git push origin :<name> //删除远程分支
git push origin <name> //用回滚后的本地分支从新创建远程分支
复制代码
这篇博客用了我很多洪荒之力,但愿对你们理解 Git 分支有所帮助,不对之处还请指出。
最近 Git 系列走起,下篇博客见!