令人困惑的地方在这里:
Git从未将这些文件视为单独的文件。Git认为一切都是完整的内容。
Git经常在自己的仓库中使用160位哈希代替对象。文件树基本上是与每个文件的内容(加上一些元数据)相关的名称和哈希的列表。
但是160位哈希值唯一地标识了内容(在git数据库的范围内)。因此,以哈希为内容的树包括处于其状态的内容。
如果更改文件内容的状态,则其哈希也会更改。但是,如果其哈希值更改,则与文件名的内容关联的哈希值也会更改。依次更改“目录树”的哈希。
当git数据库存储目录树时,该目录树暗含并包括所有子目录的所有内容以及其中的所有文件。
它以具有指向Blob或其他树的(不变,可重用)指针的树结构进行组织,但是从逻辑上讲,它是整个树的整个内容的单个快照。该代表在git的数据库是不平坦的数据内容,但在逻辑上是所有的数据,并没有其他的。
如果将树序列化到文件系统,删除所有.git文件夹,并告诉git将树重新添加到其数据库中,您最终将不向数据库添加任何内容-该元素已经存在。
将git的哈希值视为指向不变数据的参考计数指针可能会有所帮助。
如果您以此为基础构建了一个应用程序,则文档就是一堆页面,这些页面具有层,层,组和对象。
要更改对象时,必须为其创建一个全新的组。如果要更改组,则必须创建一个新图层,该图层需要一个新页面,该页面需要一个新文档。
每次更改单个对象时,它都会产生一个新文档。旧文档继续存在。新旧文档共享它们的大部分内容-它们具有相同的页面(除了1)。该页面具有相同的层(除了1)。该层具有相同的组(除了1)。该组具有相同的对象(1个除外)。
同样,从逻辑上讲,我的意思是一个副本,但是在实现方面,它只是指向同一不可变对象的另一个引用计数指针。
一个git repo很像那样。
这意味着给定的git changeset包含其提交消息(作为哈希码),其工作树以及其父更改。
这些父级更改一直包含其父级更改。
git 历史记录中包含历史记录的部分是该变化链。在一个水平的变化呢那链上面的“目录”树-从“目录”树,你不能唯一地得到一个变化集和变化的链条。
要了解文件发生了什么,请从变更集中的该文件开始。该变更集具有历史。通常,在该历史记录中,存在相同的命名文件,有时具有相同的内容。如果内容相同,则文件没有更改。如果不同,那就有所变化,需要做一些工作才能弄清楚到底是什么。
有时文件不见了;但是,“目录”树可能包含另一个具有相同内容的文件(相同的哈希码),因此我们可以用这种方式进行跟踪(请注意;这就是为什么您希望将提交文件与提交文件分开移动的原因) -编辑)。或相同的文件名,并且检查后文件足够相似。
因此git可以将“文件历史记录”拼凑在一起。
但是,此文件历史记录来自“整个变更集”的有效解析,而不是来自文件一个版本到另一个版本的链接。