Git三大特点之Branch(分支)

我习惯每篇博客都有个开篇

还记得 Git 系列第一篇 Git 自我介绍的话吗?其中有 Git 本身都赞同的三大特点git

cheap local branching, convenient staging areas, and multiple workflowsbash

轻量的本地分支, 方便的暂存,以及多工做流。其中由于有分支的存在,才构成了多工做流的特点,因此 Branch 不愧为 Git 的王牌特点。这篇博客,主要和你们一块儿学习一下轻若鸿毛,帅到炸裂的分支儿。微信

Branch 的概念

分支的概念,在我看来,分两个版本:学习

从使用场景上解释,是这么个概念spa

Git 的分支,就是开发过程当中,要选择的一条路,你能够选择和其余小伙伴一块儿走同一条路,也能够本身走一条路,路与路之间相互没有影响,做为路的主人,你也随时可让两条路合并。命令行

简笔画 Git 分支

深刻一点的话,是这么个概念3d

Git 的分支,其实本质上仅仅是指向提交对象的可变指针,这个可变指针,指向路的终点。同时,还有一个比较特别的 HEAD 指针,用于记录当前工做的位置,借用上面的例子,这个 HEAD 指针等于在路上走的你本身,你在哪,指针就在哪,你在哪一个分支,HEAD 指针就指向哪一个分支的指针。 指针

深层次的分支概念图

实际上,当咱们使用 Git 的时候,咱们就使用了分支,由于 Git 的默认分支名字是 master,若是你有心的话,会发现执行 git init后,命令行的输出头部已经默认在 master 分支了。 可是这个时候,还并未建立 master 分支,只有当有一个提交的时候,才会建立 master 分支。缘由在于,分支的指针要指向提交的呀,忽然明白了,当初看 Android Studio 的教程,为何每一个都让有一个初步提交了呢。code

无图无真相,不信的看下面:cdn

git 默认分支 master

玩转 Branch 必备技能

有关分支的命令很少,无非是换着花样的增删改查,掌握好如下基本的命令,之后就能够在 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 指针指向要切换的分支的指针处。

使用场景有两个:

  1. 已经存在的分支,如今要切换过去。
git checkout <name>
复制代码
  1. 建立一个新分支,并切换到新分支,这个一步到位的话须要 -b 参数。

    以当前分支为基础,建立一个新分支

    git checkout -b <branch name>
    复制代码

    以指定的某一个提交,建立一个新分支

    git checkout -b <branch name> <SHA1>
    复制代码

合并分支

以上,是分支的增删改查独立操做,可是 Git 创造这个分支,并不仅是为了让它们自个儿和自个儿玩的,还须要它们之间的相互协做和配合。 就像写项目的时候,分好开发任务,你和你的小伙伴新建了两个分支,你写你的 Anglela,他写他的 baby,到开发完成以后,确定要合在一块儿,才能成就 Anglelababy。合的这个动做,就涉及到了分支合并的概念。

分支合并使用到的命令是

git merge <branch name>
复制代码

分支合并相对分支的其余操做,是相对要复杂一点的,怎么说也是多分支操做,至少要对得起它一听就比较高端的名字吧,因而我决定把分支的合并做为一个大标题。

Branch 合并是大事

git 的两种合并模式

分支的合并是很是智能的,目前有两种模式,两种模式的选择,不须要咱们参与,而是 Git 根据分支状况不一样,自行判断选择的。在我使用 Git 的过程当中,执行分支合并,有时须要输入提交信息,有时不须要,做为小白的我懵的不知因此然,后来才知道是由于合并模式的问题。

两种模式是:

  1. Fast-Forward(快进式)(PS:这个名字是官方的)
  2. Recursive Strategy Merge(策略合并式)(PS:这个名字非官方,我本身起的,有时也叫三方合并式)
  • Fast-Forward(快进式)

如图,有两个分支,master 分支和 feature 分支。当这两个分支处于上面的关系时,当进行合并操做时,就会出现 fast-forward。

缘由是;因为当前 master 分支所指向的提交是 feature 分支的直接上游,因此 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,若是顺着一个分支走下去可以到达另外一个分支,那么 Git 在合并二者的时候,只会简单的将指针向前推动(指针右移),由于这种状况下的合并操做没有须要解决的分歧——这就叫作 “快进(fast-forward)”。

合并后的分支指针位置以下:

  • Recursive Strategy Merge(策略合并式)

这个合并方式,是为补充 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!保存并退出页面。

合并成功后的提示信息:

画出上面小例子的分支合并,示意图,以下:

master 合并 featureA

master 合并 featureB

和平解决 Branch 合并冲突

有人在的地方就有江湖,有分支在的地方,就有冲突。有时候合并操做不会如此顺利。 若是你在两个不一样的分支中,对同一个文件的同一个部分进行了不一样的修改,Git 就无法干净的合并它们,因而就会发生冲突。

以下,分别在 master 和 featureA ,在 master.txt 文件第一行添加一句话,而后两个分支合并,就会发生冲突。

冲突提示信息中,指明冲突文件为 master.txt。同时,也能够经过 git status 命令,查看冲突的详细信息

须要说明的是,若是遇到冲突的话,git 就没法自动合并了,接下来要靠咱们本身手动解决冲突,方法是:

  1. 查看形成冲突的文件,修改冲突部分
  2. 对修改后冲突文件,执行 git add操做
  3. 建立一个修改冲突的提交。

先知道一下思路,有个简单的概念在脑子里,接下来,一步一步仔细看~

第一步:查看形成冲突的文件,修改冲突部分

冲突文件 master.txt 以下,git 虽然没法解决冲突, 可是已经帮咱们帮到最后了,使用简单的三个符号,标明了冲突的地方,以及冲突的两个分支在该地方发生冲突内容。

符号 意义
======= 分隔符
<<<<<<< HEAD 至 ======= master 分支中该地方的内容
======= 至 >>>>>>> featureA featureA 分支中该地方为内容

接下来编辑 master.txt 文件,完成合并,确认以后,把 git 冲突标识符号给删除掉便可。

第二步 & 第三步:修改后冲突文件,add && commit

分支回滚, 有后悔路能够走

现实中,不免有些时候,你会有后悔的念头。例如天天我迟到的时候,都会后悔为何第一遍闹钟响的时候没有起床,可是这个世界,没有后悔路能够走,我只能努力作到明天早起。

可是,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 系列走起,下篇博客见!


欢迎关注博主的微信公众号,快快加入哦,期待与你一块儿成长!

欢迎关注博主的微信公众号,快快加入哦,期待与你一块儿成长!
相关文章
相关标签/搜索