2.2 Git的简短历史(A short history of Git)
正如世间许多伟大的事情,Git起源于一些创造性的破坏和激烈的争论。Linux内核(kernel)是一个相当大范围的开源软件工程。在Linux Kernel维护期的大部分时间段内,对软件的更改都以补丁包和归档文件的方式来传递。2002年,Linux Kernel项目开始使用私有的DVCS系统BitKeeper.
2005年,开发Linux内核的社区和开发商用软件BitKeeper的公司之间的关系崩裂了,这个工具免费的状态被取消。这促使linux开发社区(尤其是Linus Torvalds, Linux的创始人)开始开发他们自己的工具。这个工具将建立在一些他们在使用BitKeeper时学到的经验。新系统的一些主要目标如下:
- 速度
- 简单设计
- 强力支持非线性开发(数千并行的分支)
- 完全分布式
- 能够有效地处理象Linux Kernel这样的大型项目(在速度上和数据大小上)
自从它在2005诞生以来,Git已经演进和成熟为非常容易使用且保留了这些初始特性的系统。它难以致信的快速,非常高效足以处理一些大型项目,而且它具有一个难以致信的分支系统来保证非线性开发 (如第3章所述).
2.3 Git 基础 (Git Basics)
那么,简而言之,什么是 Git ? 本节是一个非常重要的章节需要你的吸收,因为如果你理解了什么是Git而且理解其如何工作的基本原理,那么有效的使用 Git将可能会非常简单。当你在学习Git时,请试图在脑海中忘掉你可能知道的一些其它的VCS系统诸如Subversion和perforce等,这样做的目的是在你使用Git时避免一些细微的混淆。Git 存储和考虑信息非常不同于其它的系统,尽管用户界面是相当的相似;理解这些不同可以帮助你避免在使用过程中出现混淆。
2.3.1 快照而非不同(Snapshots, Not Differences)
Git和其它VCS(包括Subversion 和 friends)最主要的不同是Git考虑数据的方式。从理论上来说,大多数的系统以基于文件的变更列表来存储信息。这些系统(CVS, subversion, perforce, Bazaar等等)把他们保持的信息看作是一系列的文件以及随着时间对这些文件所做的变更,如图1-4所示:
Git 并不是以这种方式存储它的数据的,相反,Git把它的数据看作是一个迷你文件系统的快照组。每次当你在Git中提交或存储项目状态时,它基本上是拍照了当前系统的所有文件并存储一个参考到那个快照中。为了更有效率,如果文件没有更新,Git不会重新存储文件――只是连接到前一个它已经存储的相同的文件上。Git考虑它的数据如图1-5所示:
这是一个Git和几乎所有其它VCS系统重要的不同。它使得Git几乎重新考虑了版本控制的每个方面,而大多数的其它系统仅仅继承于它的前一代。这也使得Git更象一个迷你的具备一些强大的工具的文件系统,而不是一个简单的VCS。在第3章,当我们讲解Git分支时,我们将探讨一些这样做的优点。
2.3.2 几乎每个操作都是基于本地的(Nearly Every Operation is Local)
大多数Git中的操作只需要本地文件和资源即可实现—通常情况下,没有什么信息是必需要从网络上的其它计算机来获取的。如果你过去常常使用一个CVCS,在这个系统中,多数的操作都会有网络开销。从这一方面来说,你会认为速度之神已经庇佑了Git以不世的力量。因为你已经在本地的磁盘上拥有了整个项目的全部历史,许多操作看起来就像是即时的。
例如,为了浏览项目的历史,Git不需要去服务器上获取历史并显示给你—它只需要直接从你的本地数据库中读取即可。这意味者你可以几乎立即看到项目的历史。如果你需要看到某个文件当前的版本和一个月前的版本之间的任何更改,Git可以查找一个月前的文件并做一个本地差异的计算,而不是向一个远端服务器查询或者从服务器上获取一个较老的版本再在本地做比较。
这也意味者当你不在线或者不在VPN时,你不可以做的事情会非常少。如果你正在飞机上或者火车上想做一点工作,你可以愉快地提交直到当你获取网络连接时再上载。如果你回家了而你的VPN client不能很好的工作,你也可以工作。在大多数其它系统中,这么做要么是不可能的,要么会非常痛苦。在perforce中,例如,当你无法连接到服务器时,你不可能做很多。而在Subversion 和CVS中,你可以编辑文件,但你无法提交更改到你的数据库中(因为库不在线)。这可能看起来不像一个大的改进,但你可能会对它造成这么重大的不同而惊奇。
2.3.3 Git 具备完整性(Git has Integrity)
Git中的任何东西在存储前都是经过校验运算并由该校验和所关联的。这意味者更改任何文件的内容或目录而不让git知道是不可能的。这个功能已经内置在Git的最低层而且集成到它的真个哲学观中。你不可能在传送过程中丢失信息或者得到了一个已经被破坏的文件而Git无法检测到。
Git用来做校验和的机制被称之为SHA-1哈希。这是一个由40个16进制字符(0-9和a-f)组成的字符串。运算基于Git中的文件内容或目录结构来实现。一个SHA-1哈希看起来象这样:
24b9da6552252987aa493b52f8696cd6d3b00373
你将会在Git的任何地方都可以看到这样的哈希值,这是因为Git在很多地方都使用了它。实事上,Git存储所有东西都不是根据文件名称而是根据Git数据库可寻址的它的内容的哈希值。
2.3.4 Git基本上只增加数据(Git Generally Only Adds Data)
当你在Git上做任何操作时,几乎所有操作只是增加数据到Git数据库中。让系统做一些不可恢复的操作或以其它方式删除数据是非常困难的。而任何VCS中,你可能会丢失或弄乱你还未提交的更改;而一旦你提交一个快照到Git中,丢失是非常困难的,尤其是当你定期的push你的数据库到另外的库中。
这使得使用Git是一个愉悦的事情;因为我们知道我们可以体验没有使事情恶化的危险。更深入的查看Git怎么存储数据以及你怎么恢复丢失的数据,请查看第9章“封面下面”(Under the Covers)。
2.3.5 三种状态(The Three States)
现在,请注意。关于Git,如果你希望在接下来的学习中过程进展顺利,这是主要的你需要记得的事情。Git有三个主要的文件状态:已提交状态(committed),已修改状态(modified)和临时阶段状态/缓存区状态(Staged)。已提交状态意味者数据已经安全的存储到了你的本地数据库中。已修改状态意味者你已经更改了文件但还没有提交到你的数据库中。临时阶段/缓存区状态意味者你已经在当前版本中标识了一个修改的文件而准备进入到你的下一个提交的快照中。
这引出了Git项目的三个主要分区:Git目录,工作目录以及临时阶段/缓存区。
Git 目录是Git用来存储元数据和你的项目对象数据库的地方。这是Git最重要的部分。这也是当你从其它计算机上clone一个库时需要copy的东西。
工作目录是一个单一的项目的检出版本。这些文件被从位于Git目录的压缩的数据库中提取出来放置在磁盘上供你使用或修改。
临时缓存区是一个简单的文件,通常包含在你的Git目录中,它用来存储你将进入到下一个commit的相关信息。它有时可以通过Index来索引,但以临时缓存区来索引已经成为标准。
一个基本的Git工作流程看起来如下:
- 你在你的工作目录下修改文件。
- 你缓存文件(stage),增加他们的快照到临时阶段区。
- 你做一个提交(commit),这将把哪些位于临时阶段区的文件快照永久存储到你的Git目录中。
如果一个文件的特定版本位于Git目录中,它被认为已经提交。如果它已经修改且已经增加到临时阶段区,它被成为已缓存(staged)。如果它自checkout后做了更改但没有被缓存。它被成为已修改的。在第2章,你将学习到更多关于这些状态并了解或者怎么利用它们或者整个跳过staged 部分。