章节 ▾ 第二版

1.3 起步 - 什么是 Git?

什么是 Git?

那么,简而言之,什么是 Git?理解这一节非常重要,因为如果你了解了 Git 的本质以及它的基本工作原理,那么高效使用 Git 对你来说会容易得多。在学习 Git 时,请尽量忘掉你可能了解的其他版本控制系统(VCS)的知识,例如 CVS、Subversion 或 Perforce——这样做有助于你在使用该工具时避免细微的混淆。尽管 Git 的用户界面与这些版本控制系统非常相似,但 Git 存储和思考信息的方式截然不同,理解这些差异将有助于你在使用时避免困惑。

快照,而非差异

Git 与其他任何版本控制系统(包括 Subversion 等)的主要区别在于 Git 对待数据的方式。从概念上讲,大多数其他系统以文件变更列表的方式存储信息。这些系统(CVS、Subversion、Perforce 等)将它们存储的信息视为一组文件以及随时间对每个文件所做的更改(这通常被称为基于增量的版本控制)。

Storing data as changes to a base version of each file
图 4. 将数据存储为每个文件的基础版本的差异

Git 不以这种方式思考或存储数据。相反,Git 更像是把数据看作微型文件系统的一系列快照。在使用 Git 时,每当你提交(commit)或保存项目状态时,Git 基本上都会对那一刻所有文件的外观进行“拍照”,并存储该快照的引用。为了高效起见,如果文件没有更改,Git 不会再次存储该文件,而只是存储一个指向之前已存储的相同文件的链接。Git 将数据视为快照流

Git stores data as snapshots of the project over time
图 5. 将数据存储为随时间演进的项目快照

这是 Git 与几乎所有其他版本控制系统之间的重要区别。这使得 Git 重新思考了绝大多数其他系统从上一代继承下来的版本控制的各个方面。这使得 Git 更像是一个在其之上构建了极其强大工具的微型文件系统,而不仅仅是一个版本控制系统。当我们讨论 Git 分支时,我们将探讨以这种方式思考数据所带来的诸多好处。

几乎所有操作都是本地的

Git 中的大多数操作只需要本地文件和资源即可运行——通常不需要来自网络中另一台计算机的信息。如果你习惯了那些大部分操作都需要网络延迟开销的集中式版本控制系统(CVCS),那么 Git 的这一点会让你觉得它被赋予了超自然的速度。因为整个项目历史记录都存储在你的本地磁盘上,所以大多数操作看起来几乎是瞬间完成的。

例如,要浏览项目历史记录,Git 不需要去服务器获取历史记录并显示给你看——它直接从你的本地数据库中读取。这意味着你几乎可以立即看到项目历史。如果你想查看当前版本的文件与一个月前的文件之间的差异,Git 可以查找到一个月前的文件并进行本地差异计算,而不必请求远程服务器执行此操作,也不必从远程服务器拉取旧版本文件在本地进行比较。

这也意味着,如果你离线或未连接 VPN,几乎没有什么事是做不了的。如果你在飞机或火车上想做点工作,你可以放心地进行提交(记住,是提交到你的本地副本),直到连接网络后再进行上传。如果你回家后无法正常连接 VPN 客户端,你依然可以工作。在许多其他系统中,这样做要么是不可能的,要么是很痛苦的。例如,在 Perforce 中,当你不连接到服务器时,几乎什么也做不了;在 Subversion 和 CVS 中,你可以编辑文件,但无法将更改提交到数据库(因为你的数据库离线了)。这看起来可能没什么大不了的,但你可能会惊讶地发现这会带来多大的差异。

Git 保证完整性

Git 中所有的数据在存储前都会进行校验和(checksum)计算,然后以该校验和来引用。这意味着不可能在不被 Git 知晓的情况下更改任何文件或目录的内容。此功能内置于 Git 的最底层,是其哲学不可或缺的一部分。你不可能在传输过程中丢失信息或导致文件损坏,而 Git 无法检测到。

Git 用于此校验和的机制称为 SHA-1 哈希值。这是一个由 40 个十六进制字符(0-9 和 a-f)组成的字符串,它是根据 Git 中文件或目录结构的内容计算出来的。SHA-1 哈希值看起来像这样

24b9da6552252987aa493b52f8696cd6d3b00373

你会在 Git 的各处看到这些哈希值,因为它们被广泛使用。事实上,Git 数据库中存储的一切不是按文件名存储的,而是按其内容的哈希值存储的。

Git 一般只添加数据

当你执行 Git 操作时,几乎所有操作都只会向 Git 数据库添加数据。很难让系统执行不可撤销的操作,或者以任何方式擦除数据。与任何版本控制系统一样,你可能会丢失或弄乱尚未提交的更改,但一旦你将快照提交到 Git 中,它就很难丢失,特别是如果你定期将数据库推送到另一个存储库的话。

这使得使用 Git 成为一种乐趣,因为我们知道我们可以进行实验,而不用担心严重搞砸。有关 Git 如何存储数据以及如何恢复看似丢失的数据的更深入探讨,请参阅 撤销操作

三种状态

请注意——如果你想让接下来的学习过程顺利,这是关于 Git 最重要的一点需要记住。Git 有三种主要状态,你的文件可能处于其中之一:已修改(modified)已暂存(staged)已提交(committed)

  • 已修改表示你已经修改了文件,但还没有将其提交到数据库中。

  • 已暂存表示你已经对一个已修改文件的当前版本做了标记,使其包含在下一次提交的快照中。

  • 已提交表示数据已经安全地存储在你的本地数据库中。

这引出了 Git 项目的三个主要部分:工作区、暂存区和 Git 目录。

Working tree, staging area, and Git directory
图 6. 工作区、暂存区和 Git 目录

工作区是项目某个版本的一次签出(checkout)。这些文件从 Git 目录的压缩数据库中提取出来,放置在磁盘上供你使用或修改。

暂存区是一个文件,通常保存在 Git 目录中,它存储了关于下一次提交将包含哪些内容的信息。在 Git 术语中,它的技术名称是“索引”(index),但“暂存区”(staging area)这个短语同样适用。

Git 目录是 Git 存储项目元数据和对象数据库的地方。这是 Git 中最重要的部分,也是你从另一台计算机克隆存储库时所拷贝的内容。

基本的 Git 工作流程如下

  1. 在工作区中修改文件。

  2. 选择性地暂存这些更改,将其放入暂存区,这意味着添加这些更改。

  3. 进行提交,将暂存区中的文件作为快照永久地存储到 Git 目录中。

如果文件的特定版本在 Git 目录中,它就被认为是已提交的。如果它已被修改并添加到暂存区,它就是已暂存的。如果它自从上次检出后被修改了但没有被暂存,它就是已修改的。在 Git 基础中,你将了解更多关于这些状态的信息,以及如何利用它们或完全跳过暂存步骤。