0、导读
本文适合对git有过接触,但知其然不知其所以然的小伙伴,也适合想要学习git的初学者,通过这篇文章,能让大家对git有豁然开朗的感觉。在写作过程中,我力求通俗易懂,深入浅出,不堆砌概念。你能够从本文中了解以下知识:
- Git是什么
- Git能够解决哪些问题
- Git的实现原理
请注意,本文的阐述逻辑是:Git是什么——>Git要解决的根本问题是什么——>git是如何解决这些问题的。
1、Git是什么?
Git是一种分布式版本控制系统。
有人要问了,什么是“版本控制”?Git又为什么被冠以“分布式”的名头呢?这两个问题我们一一解答。
版本控制这个说法多少有一点抽象。事实上,版本控制这件事儿我们一直在做,只是平时不这么称呼。举一个栗子,boss让你写一个策划案,你先完成了一稿,之后又有了一些新的想法,但是并不确定新的想法是否能得到boss的认可,于是你保存了一个初稿,之后在初稿的基础上另存了一个文件,做了部分修改完成了一个修改稿。OK,这时你的策划案就有了两个版本——初稿和修改稿。如果boss对修改稿不满意,你可以很轻易的把初稿拿出来交差。
在这个简单的过程中,你已经执行了一个简单的版本控制操作——把文档保存为初稿和修改稿的过程就是版本控制。
学术点说,版本控制就是对文件变更过程的管理。说白了,版本控制就是要把一个文件或一些文件的各个版本按一定的方式管理起来,目的是需要用到某个版本的时候可以随时拿出来。
另一个个问题,为什么说Git是“分布式”版本控制系统呢?
这里的“分布式”是相对于“集中式”来说的。把数据集中保存在服务器节点,所有的客户节点都从服务节点获取数据的版本控制系统叫做集中式版本控制系统,比如svn就是典型的集中式版本控制系统。
与之相对,Git的数据不止保存在服务器上,同时也完整的保存在本地计算机上,所以我们称Git为分布式版本控制系统。
Git的这种特性带来许多便利,比如你可以在完全离线的情况下使用Git,随时随地提交项目更新,而且你不必为单点故障过分担心,即使服务器宕机或数据损毁,也可以用任何一个节点上的数据恢复项目,因为每一个开发节点都保存着完整的项目文件镜像。
2、Git能够解决哪些问题?
就像上文举的例子一样,在未接触版本控制系统之前,大多人会通过保存项目或文件的备份来达到版本控制的目的。通常你的文件或文件夹名会设置成“XXX-v1.0”、“XXX-v2.0”等。
这是一种简单的办法,但过于简单。这种方式无法详细记录版本附加信息,难以应付复杂项目或长期更新的项目,缺乏版本控制约定,对协作开发无能为力。如果你不慎使用了这种方式,那么稍稍过一段时间你就会发现连自己都不知道每个版本间的区别,版本控制形同虚设。
Git能够为我们解决版本控制方面的大多数问题,利用Git
- 我们可以为每一次变更提交版本更新并且备注更新的内容;
- 我们可以在项目的各个历史版本之间自如切换;
- 我们可以一目了然的比较出两个版本之间的差异;
- 我们可以从当前的修改中撤销一些操作;
- 我们可以自如的创建分支、合并分支;
- 我们可以和多人协作开发;
- 我们可以采取自由多样的开发模式。
诸如此类,数不胜数。然而实现这些功能的基础是对文件变更过程的存储。如果我们能抓住这个根本,提纲挈领的学习git,会事半功倍。
随着对Git更深入的学习,你会发现它会变得越来越简单,越来越纯粹。道家有万法归宗的说法,用在这里再合适不过。因为Git之所以有如此多炫酷的功能,根源只有一个:它很好的解决了文件变更过程存储这一个问题。
所以,如果问“Git能够解决哪些问题?”我们可以简单的回答:Git解决了版本控制方面的很多问题,但最核心的是它很好的解决了版本状态存储(即文件变更过程存储)的问题。
3、Git的实现原理
我们说到,Git很好的解决了版本状态记录的问题,在此基础上实现了版本切换、差异比较、分支管理、分布式协作等等炫酷功能。那么,这一节我们就先从最根本的讲起,看看Git是如何解决版本状态记录(即文件变更过程记录)问题的。
我们都有版本记录的经验,比如在文档撰写的关键点上保留一个备份,或在需要对文件进行修改的时候“另存”一次。这都是很好的习惯,也是版本状态记录的一种常用方式。事实上,Git采取了差不多的方式。
在我们向Git系统提交一个版本的时候,Git会把这个版本完整保存下来。这是不是和“另存”有异曲同工之妙呢?不同之处在于存储方式,在Git系统中一旦一个版本被提交,那么它就会被保存在“Git数据库”中。
3.1 Git数据库
我们提到了“Git数据库”,这是什么玩意儿呢?为了能够说清楚Git数据库的概念,我们暂且引入三个Git指令,通过这三个命令,我们就能一探git数据库的究竟。
- git init 用于创建一个空的git仓库,或重置一个已存在的git仓库
- git hash-object git底层命令,用于向Git数据库中写入数据
- git cat-file git底层命令,用于查看Git数据库中数据
首先,我们用git init新建一个空的git仓库。(希望小伙伴们可以跟着我的节奏一起来实际操作一下,会加深理解。如果有还没有安装好git工具的同学,请自行百度安装,我不会讲安装的过程。)
我用的是ubuntu系统,在terminal下执行
| $ git init GitTest |

这一命令在当前目录下生成了一个新的文件夹-GitTest,在GitTest中,包含了一个新建的空git仓库。如果你不明白git仓库是什么,那么可以简单的理解为存放git数据的一个空间,这这个例子中,是“/home/mp/Workspace/GitTest/.git”目录。
接下来,我们看看git仓库的结构是什么样的。执行
| $ cd GitTest $ ls $ find .git |

执行结果如图所示,我们发现,GitTest目录下,除隐藏目录.git之外,并没有其他文件或文件夹。
我们通过find .git命令查看新生成的空git仓库的结构,会发现其中有一个objects文件夹,这就是git数据库的存储位置。
3.1 Git数据库的写入操作
紧接着,我们利用git底层命令git hash-object向git数据库中写入一些内容。执行命令:
| $ echo "version 1" | git hash-object -w --stdin |
这是一条通道命令,意思是把“|”前边的命令的输出作为“|”后边命令的输入。git hash-object -w --stdin 的意思是向git数据库中写入一条数据(-w),这条数据的内容从标准输入中读取(--stdin)。
