跳转到内容

底层命令与上层命令

当我们日常使用 Git 时,我们通常使用的是 git addgit commitgit checkout 等命令。这些命令被设计得尽可能用户友好,它们就像汽车的仪表盘和方向盘,让我们能够轻松驾驶。

然而,在这些命令之下,Git 还包含了一套更为基础、底层的命令。这些命令被称为 底层命令 (Plumbing commands),而那些我们日常使用的命令则被称为 上层命令 (Porcelain commands)

本章将带你揭开 Git 的引擎盖,看看它内部是如何运转的。

Porcelain 一词直译为“瓷器”,在这里引申为精致、包装好的接口。

上层命令是 Git 专门为普通用户设计的接口。它们具有以下特点:

  • 用户友好:提供清晰的输出、帮助信息和进度条。
  • 抽象:将复杂的内部操作封装成简单的逻辑动作(例如 git commit 实际上执行了创建树对象、创建提交对象、更新引用等多个步骤)。
  • 安全:包含许多检查机制,防止用户误操作导致数据丢失。

常见例子

  • git add
  • git commit
  • git status
  • git pull

Plumbing 一词直译为“管道”,意指底层的管道设施。

底层命令是 Git 的核心,它们直接操作 Git 的核心数据结构(对象数据库和索引)。它们通常用于:

  • 脚本编写:由于输出格式稳定且不包含多余的装饰信息,非常适合被脚本解析。
  • 调试:帮助理解 Git 内部状态。
  • 实现上层命令:早期的 Git 上层命令其实就是由 shell 脚本调用这些底层命令组成的。

常见例子

  • git hash-object:计算内容的哈希值并写入数据库。
  • git cat-file:查看对象的内容或类型。
  • git update-index:手动更新暂存区。
  • git write-tree:将暂存区内容写入树对象。

为了理解这两者的区别,我们尝试不使用 git add,而是使用底层命令将数据存入 Git 数据库。

首先,初始化一个新的仓库用于测试:

Terminal window
mkdir git-internals-demo
cd git-internals-demo
git init

git hash-object 命令可以计算数据的 SHA-1 哈希值,如果加上 -w 参数,它还会将数据写入 .git/objects 目录。

Terminal window
echo "Hello, Git Internals!" | git hash-object -w --stdin

输出(你的哈希值可能略有不同,取决于换行符等细节):

Terminal window
a0423896973644771497bdc03eb99d5281615b51

这个 40 位的十六进制字符串就是这条内容的“指纹”。此时,Git 已经将这段内容作为 Blob 对象 存储在 .git/objects/a0/4238... 文件中了。

我们可以使用 git cat-file 来检查刚刚写入的内容。

查看对象类型:

Terminal window
git cat-file -t a0423896973644771497bdc03eb99d5281615b51
Terminal window
blob

查看对象内容:

Terminal window
git cat-file -p a0423896973644771497bdc03eb99d5281615b51
Terminal window
Hello, Git Internals!
  • Porcelain (上层命令):给人用的。我们在日常开发中 99% 的时间都在用它。
  • Plumbing (底层命令):给机器和脚本用的。它是 Git 强大的基石。

理解底层命令能帮助我们理解 Git 是如何管理数据的。接下来的章节,我们将深入探讨 Git 的四种核心对象类型,看看它们是如何构建出我们熟悉的项目历史的。