四时宝库

程序员的知识宝库

小白也能学会的 Git 原理—图解仓库设计原理

通过本章节的学习你会了解到如何创建 Git 仓库、Git 仓库的底层实现原理以及目录结构(每个文件夹的用途)!

一、初始化 Git 仓库

1、创建仓库目录

进入到终端窗口,执行以下命令:

mkdir git-demo  #创建git-demo目录
cd git-demo  #进入git-demo目录

ls -la  #显示当前目录下包括隐藏文件/目录的所有文件的详细信

2、初始化 Git 仓库

git init  #初始化Git仓库

ls -la  #显示当前目录下包括隐藏文件/目录的所有文件的详细信
tree .git #显示.git文件的目录树

此时,在电脑中查看我们当前这个目录文件。因为.git文件夹属于隐藏目录,Mac 中可以通过 Command+Shift+. 显示隐藏文件、文件夹,再按一次,恢复隐藏。

通过对比,我们可以很清楚的看到哪些属于文件,哪些属于文件夹。

二、Git 仓库文件夹用途

#显示.git文件的目录树
?  git-demo git:(master) tree .git
.git
├── HEAD  # 指向当前分支
├── config  # 仓库的配置文件
├── description  # 仓库的描述信息,主要给gitweb使用
├── hooks  # 存放一些shell脚本,可以设置特定的git命令后触发相应的脚本
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── info  # 仓库的其他信息
│   └── exclude # 本地的排除文件规则,功能和.gitignore类似
├── objects # 所有文件的存储对象
│   ├── info
│   └── pack
└── refs # 具体的引用,主要存储分支和标签的引用
    ├── heads
    └── tags

8 directories, 15 file

三、Git 仓库设计原理

Git 仓库在设计之初,就跟传统的代码版本管理工具(如:RCS、CVS、Subversion等)不同,因为它拥有三个阶段:工作区、暂存区以及 Git 目录。比其他工具多了个工作区及暂存区,所以即使无法联网也一样能提交代码。

工作区、暂存区以及 Git 目录怎么理解呢?

引自 Git 官网 ProGit 解释:


工作区:对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。


暂存区:是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。


Git 仓库目录:是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。

以上内容理解起来可能比较抽象,那我们更具体的说明下。

(1)工作区

从电脑桌面进入到我们 git-demo 这个 Git 仓库文件夹,.git 隐藏文件夹外面的这片区域,就属于我们 Git 仓库的工作区。我们在这个区域内新建的文件,属于当下正在工作的内容,是没有被 Git 所标记的。比如我们新建一个 txt 文件看下会发生什么?

新建文件前,通过 git status 命令(用于查看在你上次提交之后是否有对文件进行再次修改)可以看到当前整个目录是非常干净的, Git 什么也没有识别到。

文件创建完成后,再次 git status 命令可以看到新文件已经被 Git 标识出来了。

同时,通过 tree .git 再查看 .git 目录,发现还是“ 8 directories, 15 files”没有发生变化。

(2)暂存区

暂存区(index)也称为 stage,是一个索引文件。因为初始化的仓库中,还没有添加任何文件放到 Git 的暂存区,故在 .git 目录中程序还没有自动创建该文件。现在我们将上面已创建好的 test.txt 文件 git add(将该文件添加到暂存区) 下。

git add test.txt #将 test.txt 文件添加到暂存区

tree .git  #查看 .git 目录

我们发现文件数量变成了“9 directories, 17 files”,比之前多出了“1 directories, 2 files”,分别是:

  • 目录:9d
  • 文件:index 和 aeafb9864cf43055ae93beb0afd6c7d144bfa4

其中,我们指的暂存区就是这个新创建出来的 index 索引文件。经过查看,发现 .git/index 是一个二进制文件,无法用编辑器直接打开查看内容。那有没有办法查看呢?可以通过以下Git 命令来查看:

git ls-files --stage #显示暂存区当前的内容
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0	test.txt

此时,再通过 git status 命令,可以看到暂存区里面只有一个新文件 test.txt,等待被提交到版本库。

注:.DS_Store 是 Mac OS 保存文件夹的自定义属性的隐藏文件,如文件的图标位置或背景色。

如果此时,对文件 test.txt 的内容进行修改,再 git add 一次暂存区会发生什么呢?

可以看到暂存区存储的 test.txt 的对象值发生变化了:从“9daeafb9864cf43055ae93beb0afd6c7d144bfa4” (此时变成了“垃圾对象”)变为“8d0e41234f24b6da002d962a26c2495ea16a425f”,这说明暂存区针对于同一个文件,总是存储着最新的内容,然后等待着被提交到版本库。

(3)Git 仓库目录

Git 仓库目录又可以称为“本地版本库”(为什么说是本地库呢?大家可以思考下)。暂存区保留本次变动的文件信息,等到修改了差不多了,就要把这些信息写入历史(即提交至本地版本库),这就相当于生成了当前项目的一个快照(snapshot)。

第一次提交完成后,会发现 .git 目录下会自动生成一些新的目录和文件,object 目录的文件可以先不用管,后续会细讲。

COMMIT_EDITMSG:是一个临时文件,存储最后一次提交的 message

logs 目录:用来记录操作信息的,其中包括两个文件:HEAD 和 refs。

—logs/HEAD:存储 HEAD 头指针的变迁记录,以 git reflog 命令展示。

—logs/refs/heads:记录分支的操作记录。

refs/heads/master:表示当前所在的分支

说了这么多,那究竟什么是我们的本地版本库呢?其实答案已明显,版本库是由 logs 目录和 refs 目录共同构成的。

下章节内容预告

通过本章节的学习,你会了解 git add 命令背后发生的故事,以及 Git 中最重要的概念“对象”的形成原理!

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接