第 4 章. 承诺
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
提交是一个快照,可捕捉 某一时刻版本库的当前状态。提交快照是串联在一起的,每个新快照都指向前一个快照。随着时间的推移,一连串的更改会以一系列的提交来表示。
Git 使用提交来记录对版本库的修改。从表面上看,Git 的提交与其他版本控制系统中的签入或提交类似。然而,相似之处只是表面现象。Git 创建和管理提交的内在机制是完全独特的。
提交时,Git 会获取索引目录当前状态的快照,并将其存储在对象存储中,这在第 2 章中有简要讨论。快照并不包含索引中每个文件和目录的副本。相反,Git 会将索引的当前状态与之前的提交快照进行比较,并在创建新提交时得出受影响文件和目录的列表。根据这个列表,Git 会为任何有变化的文件创建新的 blob 对象,为任何有变化的目录创建新的树对象,并重用任何没有变化的 blob 或树对象。
我们将在第 5 章讨论如何为提交准备索引目录。在本章中,我们将重点讨论提交时会发生什么。首先,我们将探讨如何引入提交,并了解原子变更集的重要性。然后,我们将了解如何识别提交以及如何查看提交历史。
Git 非常适合频繁提交,并提供了丰富的命令集来操作频繁提交。我们将向你展示如何通过多次提交(每次提交都有小的、定义明确的改动)来更好地组织改动,更轻松地操作补丁集。
承诺:记录的变更单位
提交是向版本库引入更改的唯一方法。 这一规定提供了可审计性和问责制。在任何情况下,版本库数据的更改都必须有提交记录!试想一下,如果版本库中的内容发生了某种改变,却没有任何记录来说明是如何发生的、是谁做的、为什么,那将是多么混乱。
提交是由开发人员明确引入的,这是最典型的情况。不过,有时 Git 本身也会引入提交。例如,合并操作会在版本库中创建一个新的提交,此外还有开发者在合并前的提交。你将在第 6 章了解更多。
创建提交的频率完全取决于你自己。从逻辑上讲,当开发处于潜伏阶段时,比如所有测试套件都通过时,您应该在明确定义的时间点上引入提交。
你可能会认为将整个索引与之前的某个状态进行比较会很耗时 ,但整个过程却快得惊人。这是因为,你可能还记得第二章的内容,每个 Git 对象都有一个 SHA1 哈希值,如果两个对象,甚至是两个子树,都有相同的 SHA1 哈希值,那么比较的对象就是相同的。因此,Git 可以通过剪枝具有相同内容的子树来避免大量的递归比较。
尽管如此,这并不意味着你应该在定期引入提交时犹豫不决。
原子更改集
每次 Git 提交都代表着 相对于前一个状态的单原子变更集。无论提交改变了多少目录、文件、行或字节、1要么全部适用,要么全部不适用。
从底层 Git 对象模型的角度来看,原子性背后的原理就更加清晰了。一个提交快照代表了所有修改过的文件和目录的状态,这也意味着它代表了一个给定的树状态。因此,两个快照之间的变更集代表了从一个树状态到另一个树状态的完整转换。同样,你只能从一种状态切换到另一种状态,而不能进行增量切换。我们将在第 7 章讨论如何推导提交之间的差异。
作为一名开发人员,这是一项重要的原则,不应该被破坏。请考虑以下将函数从一个文件移到另一个文件的工作流程。如果您在一次提交中将函数从第一个文件中移除,然后在另一次提交中将其添加到第二个文件中,那么在您的版本库历史中就会留下一个小的 "语义空白",在此期间函数就会消失。两次提交的顺序相反也有问题。在每种情况下,在第一次提交之前和第二次提交之后,代码在语义上是一致的,但在第一次提交之后,代码就有问题了。 ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access