章节 ▾ 第二版

1.3 上手 - Git 是什么?

什么是 Git?

那么,简单来说 Git 是什么?这是一个需要吸收的重要章节,因为如果你理解了 Git 是什么以及它是如何工作的基本原理,那么有效使用 Git 可能会对你来说容易得多。在学习 Git 时,尽量抛开你可能了解的其他版本控制系统(如 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 时,每次你提交或保存项目状态时,Git 基本上都会拍下你所有文件在那一刻的样子,并存储对该快照的引用。为了提高效率,如果文件没有更改,Git 不会再次存储该文件,而只是链接到它已存储的先前相同文件。Git 更多地将其数据视为快照流

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

这是 Git 与几乎所有其他版本控制系统之间的重要区别。它使得 Git 重新思考了大多数其他系统从上一代复制的版本控制的几乎所有方面。这使得 Git 更像一个带有强大工具的迷你文件系统,而不仅仅是一个版本控制系统。当我们讲到 Git 分支时,我们将探讨以这种方式思考数据所带来的一些好处。

几乎所有操作都是本地的

Git 中的大多数操作只需要本地文件和资源即可执行——通常不需要来自网络上另一台计算机的信息。如果你习惯了大多数操作都有网络延迟开销的集中式版本控制系统(CVCS),那么 Git 的这一方面会让你觉得速度之神赋予了 Git 超凡的力量。因为你的本地磁盘上就存有项目的完整历史,所以大多数操作看起来几乎是即时的。

例如,要浏览项目的历史记录,Git 不需要连接到服务器来获取历史记录并为你显示——它只是直接从你的本地数据库中读取。这意味着你可以几乎立即看到项目历史。如果你想查看文件当前版本和一个月前文件之间的更改,Git 可以查找一个月前的文件并进行本地差异计算,而不是不得不请求远程服务器进行或从远程服务器拉取旧版本文件到本地进行。

这也意味着,如果你处于离线状态或没有 VPN 连接,几乎没有什么事情是你不能做的。如果你乘坐飞机或火车,想要做一些工作,你可以愉快地提交(记住,是提交到你的本地副本),直到你获得网络连接以进行上传。如果你回家后无法使 VPN 客户端正常工作,你仍然可以继续工作。在许多其他系统中,这样做要么不可能,要么非常痛苦。例如,在 Perforce 中,当你未连接到服务器时,你无法做太多事情;在 Subversion 和 CVS 中,你可以编辑文件,但无法将更改提交到你的数据库(因为你的数据库处于离线状态)。这可能看起来不是什么大问题,但它能带来多大的不同可能会让你感到惊讶。

Git 具有完整性

Git 中的一切在存储之前都会进行校验和计算,然后通过该校验和进行引用。这意味着在 Git 不知情的情况下,不可能更改任何文件或目录的内容。此功能内置于 Git 的最低层,是其理念的组成部分。你不会在传输过程中丢失信息或遇到文件损坏而 Git 无法检测到。

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

24b9da6552252987aa493b52f8696cd6d3b00373

你会在 Git 中随处看到这些哈希值,因为它使用它们非常频繁。事实上,Git 在其数据库中存储所有内容都不是通过文件名,而是通过其内容的哈希值。

Git 通常只添加数据

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

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

三种状态

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

  • 已修改 (modified) 意味着你已更改文件,但尚未将其提交到数据库。

  • 已暂存 (staged) 意味着你已将文件的当前修改版本标记为要纳入下一次提交快照。

  • 已提交 (committed) 意味着数据已安全地存储在你的本地数据库中。

这引出了 Git 项目的三个主要组成部分:工作区 (working tree)、暂存区 (staging area) 和 Git 目录 (Git directory)。

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

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

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

Git 目录 (Git directory) 是 Git 存储项目元数据和对象数据库的地方。这是 Git 最重要的部分,当你从另一台计算机克隆 (clone) 仓库时,它就是被复制的内容。

基本的 Git 工作流程大致如下

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

  2. 你选择性地暂存你希望包含在下一次提交中的更改,这会将仅有这些更改添加到暂存区。

  3. 你执行提交,这会将暂存区中的文件原样取出,并将该快照永久存储到你的 Git 目录中。

如果文件的特定版本在 Git 目录中,则它被认为是已提交 (committed)。如果它已修改并已添加到暂存区,则它处于已暂存 (staged) 状态。如果它自检出后已更改但尚未暂存,则它处于已修改 (modified) 状态。在 Git 基础中,你将了解更多关于这些状态的信息,以及如何利用它们或完全跳过暂存部分。

scroll-to-top