章节 ▾ 第二版

10.1 Git 内部命令和外部命令

您可能从之前的某个章节直接跳到了这一章,也可能是一路顺读到这里的——无论哪种情况,这一章将介绍 Git 的内部工作原理和实现。我们认为理解这些信息对领会 Git 的实用性和强大功能至关重要,但也有人认为这对初学者来说会令人困惑且不必要地复杂。因此,我们将这一章放在了本书的最后,您可以选择早读或晚读。决定权在您。

现在您已经到了这里,让我们开始吧。首先,如果还不清楚,Git 本质上是一个内容可寻址的文件系统,其顶部覆盖了一个版本控制系统(VCS)的用户界面。您很快就会更深入地了解这意味着什么。

在 Git 的早期(主要是 1.5 版本之前),用户界面更加复杂,因为它更侧重于文件系统本身,而不是一个完善的版本控制系统。在过去的几年里,UI 已经得到了改进,变得像任何其他系统一样简洁易用;然而,关于早期 Git UI 复杂难学的刻板印象依然存在。

内容可寻址的文件系统层非常酷,我们将在本章首先介绍它;然后,您将学习到您最终可能需要处理的传输机制和仓库维护任务。

内部命令和外部命令

本书主要介绍了如何使用 Git 的大约 30 个子命令,如 checkoutbranchremote 等。但由于 Git 最初是一个版本控制系统的工具集,而不是一个完整的用户友好型版本控制系统,它包含许多执行底层工作的子命令,这些命令设计为可以像 UNIX 一样链式调用,或从脚本中调用。这些命令通常被称为 Git 的“内部命令”(plumbing commands),而更用户友好的命令则被称为“外部命令”(porcelain commands)。

正如您现在可能已经注意到的,本书的前九章几乎完全涉及外部命令。但在本章中,您将主要接触更底层的内部命令,因为它们让您能够访问 Git 的内部工作原理,并有助于展示 Git 如何以及为何执行其操作。其中许多命令并非设计为直接在命令行上手动使用,而是作为构建新工具和自定义脚本的积木。

当您在新的或现有的目录中运行 git init 时,Git 会创建一个 .git 目录,Git 几乎所有存储和操作的数据都位于其中。如果您想备份或克隆您的仓库,将这个目录复制到别处就可以获得几乎所有您需要的东西。本章基本上都围绕着这个目录中的内容展开。一个新初始化的 .git 目录通常看起来是这样的:

$ ls -F1
config
description
HEAD
hooks/
info/
objects/
refs/

根据您的 Git 版本,您可能会看到一些额外的内容,但这是一个新的 git init 仓库——这是默认情况下的样子。description 文件仅由 GitWeb 程序使用,所以不用担心它。config 文件包含您的项目特定配置选项,info 目录保存了一个全局忽略文件,用于存放您不想在 .gitignore 文件中跟踪的模式。hooks 目录包含您的客户端或服务器端钩子脚本,这些脚本将在 Git Hooks 中详细讨论。

这就剩下四个重要的条目:HEAD 文件、(尚未创建的)index 文件,以及 objectsrefs 目录。这些是 Git 的核心部分。objects 目录存储了您的数据库的所有内容,refs 目录存储了指向该数据中提交对象的指针(分支、标签、远程仓库等),HEAD 文件指向您当前检出的分支,index 文件是 Git 存储暂存区信息的地方。接下来,我们将详细探讨这些部分,以了解 Git 的工作方式。