git分支

什么是git分支?

什么是git分支?首先让我们回顾一下提交对象,一个提交对象(commit objects)包括:

一系列文件在某个时间的快照。

一系列指向父提交对象的索引。

一个SHA-1名字,这个名字40个字符长,是独一无二的。

作者的姓名和邮箱,以及提交时对提交的描述。

事实上,“一系列文件在某个时间的快照”并不是直接存在于提交对象。在git中,blob对象保存着文件的快照,树对象保存着目录结构和blob对象的索引,而提交对象保存指向树对象的指针。下图是一个这三者关系的示意图:

三个对象及其关系

那么git中的分支是什么呢?

git中的分支就像是你的文件的一份副本,你可以在需要的时候拷贝一份出来,这样你就得到了一个“分支”,你可以在上面修改,修改完成之后再合并回去。在一些版本控制软件中实际情况确实是这样,然而在git中并非如此。

在git中,对分支的操作大部分只是在修改指向提交对象的heads。我们知道,heads是一个指向提交对象的指针,分支操作中的大部分操作只需要修改heads的指向,即向heads文件中写入41个字符即可(40个SHA-1字符串和1个换行符)。与其他一些版本控制软件采用的复制文件策略相比较,git分支操作与文件大小无关,操作迅速快捷。

指向提交对象的heads

创建分支

现在先来看看我们在哪个分支,使用命令查看当前分支,命令选项显示分支指向提交对象的校验和及其描述:

从结果中看到,现在只有一个分支,叫做。表示当前所在的分支,即HEAD的指向。

用图简略表示如下:

仅有master分支

现在创建一条分支,使用命令:

现在有了两条分支:和,目前我们在分支。图示如下:

创建一条dev分支

可见,事实上只是创建了一个指向图中提交对象的指针,使用可以查看heads的指向:

、远程的和指向提交对象,指向。

切换分支

现在切换到分支,使用命令,在切换前请确保你的工作目录是干净的:

这样就切换到了分支,查看一下:

可以看到我们确实在分支,确实指向了分支。在切换分支时,git会将分支所指向的提交对象的文件快照检出到工作目录,并且更改的指向。目前分支情况图示如下:

切换到dev分支

可以创建分支并且切换到它,相当于执行下面两条命令:

“快进”合并

现在在分支,我们创建一个文件并且提交:

查看一下各个分支所指:

前进了一个提交对象,指向,其他分支并没有更改,图式如下:

dev新提交

现在切换到,使用命令,会指向,工作目录中的文件将会被替换:

切换回master

合并分支使用命令,这个命令将分支合并到当前分支,现在我们在分支,执行下面的命令将分支合并到分支:

git告诉我们此次合并的方式是(快进),此时分支情况如下:

合并dev分支

现在分支已经被合并到分支了。从上图可以看出git仅仅是简单的更新了和的指向,这是由于合并前指向的直接上游,这种合并方式叫做快进(Fast-forward)。

可以使用选项避免使用“快进”合并,这样会形成一个新的合并提交,类似下节讲到的分之合并:

现在分支已经充分得发挥了自己的作用,让我们删除它:

如果一个分支没有完全合并到当前分支,那么git会阻止你删除它,如果确实要删除它,使用命令选项:

如果想要知道那些分支被合并了或者没有合并,使用下面的命令:

目前分支情况如下:

删除dev分支

本文所讲的例子整体过程图示如下:

快进合并

分支合并

现在创建一个分支并且切换到该分支:

添加并提交,修改并提交:

回到分支并且修改:

现在两条分支在分叉后都有新的提交:有两个新的提交,有一个新的提交。怎样在命令行查看呢?

可以看到,在分支分叉,之后进行了两次提交,进行了一次提交,目前我们在分支。图示如下:

合并提交1

现在将分支合并到分支:

现在git帮我们合并了和,并且生成了一个新的提交(你可能需要填写提交描述),这个新提交的SHA-1校验和前七位是8425ef2。

git能够帮我们自动合并,而不会产生冲突的原因是我们在不同的分支中修改了不同的文件,此时git会参考两个分支所指的快照(的和的)和两个分支的共同祖先(),自动合并。参考的三个快照分别相当于下图的C6、C7和C4.

新生成的提交叫做合并提交,相当于下图的C8.这个新提交拥有两个父提交。

合并提交2

好了,现在删掉分支吧:

本文所讲的分支合并的整体过程图示如下:

分之合并

冲突解决

如果在不同分支中同一个文件的同一个地方做了修改,git就无法干净利落地合并它们。

创建一个新的分支,在分支中将修改如下并且提交:

切换到分支,将修改如下并且提交:

现在将分支合并到分支:

git告诉我们说自动合并失败,原因是在文件中有冲突,并且提醒我们解决冲突后提交结果。

也就是说,git在遇到冲突时,并不会创建一个合并提交,而是暂停下来,等用户解决冲突之后,由用户提交。

含有冲突的文件被标记为“未合并”(unmerged)状态,随时可以使用来查看:

现在让我们解决中的冲突,首先来看一看git刚刚所做的工作:

其中的一部分是git为我们标记的冲突的部分:

在的上半部分的是分支中的文件内容,在其下半部分的是分支中文件的内容。

现在让我们将这部分修改如下:

这表示将丢弃中的修改,当然你可以根据自己的喜好更改,你可以改成任意你需要的内容。

现在将文件添加到暂存区,并且查看状态:

可见,一旦冲突文件被添加到暂存区,它的“未合并”状态就会被解除,即表示冲突已经解决。

现在提交即可:

最后删除分支:

储藏与清理

git在切换分支时必须保证当前工作目录是干净的,如果现在做了一点更改,不至于提交一次新的更新,但是却必须更换到另一条分支上,怎么办呢?

git为我们提供了(储藏)工具。

现在在分支上对作一些更改,并且将它储藏起来:

在运行之后工作目录就变干净了,现在就可以切换到其他分支工作啦。

在其他分支工作完之后,又回到,怎样继续工作呢?

使用命令可以查看储藏的列表:

使用即可应用,如果为空,则会应用最新的储藏:

我们的更改又回来了,使用删除相应的储藏,如果为空,则会删除最新的储藏:

可以使用直接应用最新的储藏,同时删除该储藏。

在git中,可以进行多次储藏,也可以在不同的分支应用储藏。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180110G0ZAIO00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券