开篇
你可能遇到过
如果你遇到这个场景,那你可能需要版本控制。
什么是版本控制
版本控制最主要的功能就是追踪文件的变更。它将什么时候、什么人更改了文件的什么内容等信息忠实地了已录下来。每一次文件的改变,文件的版本号都将增加。除了记录版本变更外,版本控制的另一个重要功能是并行开发。软件开发往往是多人协同作业,版本控制可以有效地解决版本的同步以及不同开发者之间的开发通信问题,提高协同开发的效率。并行开发中最常见的不同版本软件的错误(Bug)修正问题也可以通过版本控制中分支与合并的方法有效地解决。
版本控制分为集中式、本地式、分布式。
Git:分布式版本控制
git 是一套以键值存储的文件寻址系统。
工作区
Workspace:工作区
Index:暂存区
Repository:仓库
Remote:远程仓库
数据存储原理
SH1A 算法
哈希算法的一种。对文件内容进行计算,可以得到一个哈希值,形如 5453545dccd33565a585ffe5f53fda3e067b84d8
。
对于内容不同的对象,会计算得到不同的SHA1哈希值。
几种类型文件
Git 目录(.git/objects/)的几种(对象)类型文件:
blob
用来存储文件内容,或者说表示一个(完整的)文件,而不仅仅只是差异存储。
Git 通过使用 zlib 压缩文件,可以有效地压缩文本文件的体积。因此 Git 比较适用于对文本文件的管理,对于二进制文件(比如音频、视频)则压缩比不大。
每个 blob 对象都会通过 SHA1 算法生成哈希值作为指针(或者叫索引、Key等),指向该文件的压缩。
两个一样内容只是名字不同的文件,会共享同一个 blob 对象。因为内容的 SHA1 是一样的。
index
这里说的 index 就是上面说的暂存区的实体存在,其实是一个文件,位于 .git/index
,直接打开会乱码,可以使用命令 git ls-files --stage
查看:
git ls-files --stage
----
100644 92390d97e4159df5c7ef31baf03c8a3378c93395 0 a.txt
100644 ff532afc325d8a07df0e2e3cb37bbee271d05840 0 dirb/b.txt
里面记录了所有跟踪文件的 blob 对象的哈希值,以及文件的路径。
如果文件内容没有改变,index 里则一直指向旧的哈希值。
tree
代表的是目录结构,或者简单理解为代表一个目录。tree 对象也会通过 SHA1 算法生成哈希值作为指针。tree 对象中包含一条或多条 blob 的指针。
目录结构如果是一样的,会共享同一个 tree 对象。
commit
commit 存储一次提交的信息,包括 tree、blob,父节点(的 commit id),以及提交的作者是谁等信息。
commit 的 ID 值就是对对象内容进行 SHA1 算法得到的哈希值。
如何存储数据
git add,生成 blob 文件,同时 index 文件中记录。
git commit 时,根据 index 文件中记录的内容,生成 tree 对象和 commit 对象。
一些概念
分支
体现在目录的 ./git/refs/heads/
中,这里包含master和一些其他分支文件。每个分支文件保存的是一个 commitID
。
标签
其实就是保存了 commitID
常用命令
了解了原理后,再回过头来看一些常用的 Git 命令:
git add
git commit
git pull
git push
...
结语
分享个小故事。大家应该都知道 Linux ——世界上最知名的开源操作系统,Android 系统就是基于 Linux 内核开发。它由 Linus Torvalds 在 1991 年发明,并最终经由开源社区的无数个开发者共同开发,至今仍然是最充满生命力的操作系统之一。
2005 年,Linux 开发团队一直使用的商业版本控制系统 BitKeeper 宣布不再免费授权社区使用,Linus 在各种交涉无果后,花了两周时间自己用 C 写了一个分布式版本控制系统并且开源了,一个月之内整个 Linux 系统的源码就交由 Git 管理了。至此之后 Git 迅速成为最流行的版本控制系统之一。2008 年,Github 网站上线,为开源项目免费提供 Git 存储,总多知名项目纷纷迁移至 Github,同时也造福了无数的个人开发者。