上一小节中,我们通过介绍Git的设计思想让读者了解了Git整体结构。现在,让我们通过一些小例子来帮助读者更好的理解。在本小节中,我会创建一个Git仓库,在创建过程中带领读者从底层了解Git是如何工作的。所以当读者阅读时,可以跟着这些例子一起做,有助于理解:
$ mkdir sample; cd sample
$ echo 'Hello, world!' > greeting
首先我们在文件系统中创建了一个名为sample
的目录,很显然在这个目录中有一个内容为Hello world!
的文本文件。至此我们还没有创建Git仓库,但是我已经可以开始通过使用一些基础的Git的命令来了解Git在创建仓库的时候将会做的事情。首先我得知道Git将会使用什么Hash编码来代表greeting
这个文件:
$ git hash-object greeting
af5626b4a114abcb82d63db7c8082c3c4756e51b
如果你也在你的系统中运行这个命令,也会得到完全一样的Hash码。这就像我们前面的章节所说的说的,即使在两个不同的Git仓库中,相同内容的文件greeting
也将使用相同的id来保存,甚至在整个互联网上也是一样的。(译者注:这是由于hash算法相同)有意思的是,我们甚至可以从另外一个人的仓库中把文件拉取到我的本地仓库。在这过程中,Git即使知道这个文件来自两个不同的仓库,但是只要他们的内容是一致的,Git就只会保存一份副本!
下一步Git将会初始化一个新的仓库,并把文件greeting
提交到这个仓库中。首先,我们使用一条Git命令来做这件事情,但是之后我们将使用更加细致的命令分步执行,以便读者了解在git init,git add,git commit这些简单的语句的背后,Git实际上做了什么:
$ git init
$ git add greeting
$ git commit -m "Added my greeting"
在这个时候,我们的greeting
文件对应的blob应该已经像我们预想的一样,在仓库中生成了,并且使用的是我们在上一步生成的那个Hash码。为了方便起见,Git只需要显示足够多位的Hash码来区别不同的文件。大部分情况下,6位hash码就足以区分所有不同的文件,因此我们就会看到下面的输出:
$ git cat-file -t af5626b
blob
$ git cat-file blob af5626b
Hello, world!
就是这样!我甚至不用知道这个文件具体被哪一个Commit所有,也不用知道它属于哪一棵“树”,仅仅通过该文件的内容,我们就可以确定这个文件存储在哪里,是不是很神奇?更有趣的是,不管这个文件被保存多长时间,总是以相同的hash保存他,通过Hash码也也可以确保这个文件永远不被修改。
Git通过这种方法将所有的文件数据保存在仓库中,更准确的说,整个Git系统就是为了以某种方式管理所有的blob,我们将会在之后的小结中了解如何管理这些blob。