刚开始使用git的时候,总想拿git来和cvs或者svn来作对比,但不久后发现这个想法本身就是错的,git完全就是另外一种物种,一种本属于未来的物种。它的对象存储方式,快照,分支等,都是完全不同的。
 
相信每个使用git的人,都想了解git内存文件的存储对象,快照,提交在历史和分支等内部的原理。都想知道它是否有传说中的那么强大?
 
 
Git 对象
先从本地创建一个空git仓库开始
 
$ mkdir test
$ cd test
$ git init
Initialized empty Git repository in /Users/lyc/Desktop/test/.git/
这时会发现目录下只有一个.git文件夹,进去后长这样

.git/
|--HEAD
|--config
|--description
|--hooks
| |--applypatch-msg.sample
| |--commit-msg.sample
| |--post-commit.sample
| |--post-receive.sample
| |--post-update.sample
| |--pre-applypatch.sample
| |--pre-commit.sample
| |--pre-rebase.sample
| |--prepare-commit-msg.sample
| |--update.sample
|--info
| |--exclude
|--objects
| |--info
| |--pack
|--refs
  • description文件仅供GitWeb使用,不用关心它。
  • config文件包含了项目特有的配置选项,如最常用的用户名和邮箱。
  • info目录保存了一份不希望在 .gitignore 文件中管理的忽略模式 (ignored patterns) 的全局可执行文件。这个用得比较少,也不用太关心。
  • hooks目录保存了客户端或服务端钩子脚本,一般我们都是用默认的,很少改,也不用太关心。

因此,我们需要重点关心另外四个重要的文件或目录:HEAD和index文件,objects和refs目录,因为它们是Git的核心:

  • objects 目录存储所有数据内容。
  • refs 目录存储指向数据 (分支) 的提交对象的指针。
  • HEAD 文件指向当前分支。
  • index 文件保存了暂存区域信息。
 
刚初使化的一个 Git 仓库, objects 目录是空的:
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
Git 初始化了 objects 目录,同时在该目录下创建了 pack 和 info 子目录,但是该目录下没有其他常规文件
 
接下来,我们新建一个文件test1.txt,内容为test1,并把它加入暂存区
$ echo test1 > test1.txt
$ git add test1.txt
发现.git目录下多了2个文件,且内容都为字节码:
.git/
|--index
|--objects
| |--a5
| | |-- bce3fd2565d8f458555a0c6f42d0504a848bd5
$  find .git/objects
.git/objects
.git/objects/a5
.git/objects/a5/bce3fd2565d8f458555a0c6f42d0504a848bd5
.git/objects/info
.git/objects/pack
在.git目录下多了一个index文件
在objects下面多了一个a5文件夹,文件夹下有一个文件名为bce3fd2565d8f458555a0c6f42d0504a848bd5的文件
 
使用如下命令查看test1.txt的hash值
 
$ git hash-object test1.txt
a5bce3fd2565d8f458555a0c6f42d0504a848bd5
发现结果的前2位是文件夹的名字,后38位是文件的名字。
 
a5bce3fd2565d8f458555a0c6f42d0504a848bd5这个文件是用zlib压缩的
通过git cat-file 命令可取出文件存储的内容
 
$ git cat-file -p a5bce3fd2565d8f458555a0c6f42d0504a848bd5
test1
内容就是test1.txt的文件内容
 
看看index文件,刚刚了解了index 文件保存了暂存区域信息, 用git ls-files —stage命令可查看index内容
 
$ git ls-files --stage
a5bce3fd2565d8f458555a0c6f42d0504a848bd5 test1.txt
此时index保存的就是新加入暂存区的文件快照
 
gitt使用'blob ' + len(content) + '\0' + content作为文件内容,其sha1值的前2位作为文件夹名,后38位作为文件名
 
 
Tree(树)对象
接下去来看 tree 对象,tree 对象可以存储文件名,同时也允许存储一组文件。Git 以一种类似 UNIX 文件系统但更简单的方式来存储内容。所有内容以 tree 或 blob 对象存储,其中 tree 对象对应于 UNIX 中的目录,blob 对象则大致对应于 inodes 或文件内容。一个单独的 tree 对象包含一条或多条 tree 记录,每一条记录含有一个指向 blob 或子 tree 对象的 SHA-1 指针,并附有该对象的权限模式 (mode)、类型和文件名信息。
 
现在把test1.tst提交,作为仓库的第一次提交
$ git commit -m "first commit"
[master (root-commit) a3951d5] first commit
file changed, insertion(+)
create mode test1.txt
 
发现在objects目录下多了两个文件夹,文件夹下面是对面的sha1文件
 
$  find .git/objects
.git/objects
.git/objects/a3
.git/objects/a3/951d57b1413275b171d967fa67fd90eecff648
.git/objects/a5
.git/objects/a5/bce3fd2565d8f458555a0c6f42d0504a848bd5
.git/objects/c0
.git/objects/c0/da834e42dcbf7b2b1c4a97925bef105d3863a3
.git/objects/info
.git/objects/pack
分别查看一下内容
$ git cat-file -p a3951d57b1413275b171d967fa67fd90eecff648
tree c0da834e42dcbf7b2b1c4a97925bef105d3863a3
author lyc <yechenli2009@gmail.com> +
committer lyc <yechenli2009@gmail.com> + first commit $ git cat-file -p c0da834e42dcbf7b2b1c4a97925bef105d3863a3
blob a5bce3fd2565d8f458555a0c6f42d0504a848bd5 test1.txt
 
其中第一个是commit对象,第二个是tree对象
 
这个tree对象可以认为是git仓库的根目录,类似unix文件系统中的"/"。
 
Commit(提交)对象
我们在根目录新建一个文件夹temp,在temp下面添加一个文件test2.txt,文件内容为test2,并提交
$ mkdir temp
$ cd temp/
$ echo "test2" > test2.txt
$ git add temp
$ git commit -am “second commit"
 
发现objects下面又多了4个文件夹,以及文件夹下对面的sha-1文件
$ find .git/objects
.git/objects
.git/objects/
.git/objects//0cf8328022becee9aaa2577a8f84ea2b9f3827
.git/objects/
.git/objects//592c587f70cf6ec1b99bb382bec2ef92f83396
.git/objects/9e
.git/objects/9e/7b8054ac3ca530d8e69556dff5903cdcbdc4d3
.git/objects/a3
.git/objects/a3/951d57b1413275b171d967fa67fd90eecff648
.git/objects/a5
.git/objects/a5/bce3fd2565d8f458555a0c6f42d0504a848bd5
.git/objects/c0
.git/objects/c0/da834e42dcbf7b2b1c4a97925bef105d3863a3
.git/objects/d2
.git/objects/d2/5d2289339c751ff3f7e1ef1865a58c71d0f51c
.git/objects/info
.git/objects/pack
 
通过git log命令来查看提交历史
$ git log
commit d25d2289339c751ff3f7e1ef1865a58c71d0f51c
Author: lyc <yechenli2009@gmail.com>
Date: Sun Oct :: + second commit commit a3951d57b1413275b171d967fa67fd90eecff648
Author: lyc <yechenli2009@gmail.com>
Date: Sun Oct :: + first commit
 
发现最后一次提交的sha-1文件是d25d2289339c751ff3f7e1ef1865a58c71d0f51c,对应文件是
 
.git/objects/d2/5d2289339c751ff3f7e1ef1865a58c71d0f51c
 
我们查看d25d2289339c751ff3f7e1ef1865a58c71d0f51c里的内容
 
$ git cat-file -p d25d2289339c751ff3f7e1ef1865a58c71d0f51c
tree 35592c587f70cf6ec1b99bb382bec2ef92f83396
parent a3951d57b1413275b171d967fa67fd90eecff648
author lyc <yechenli2009@gmail.com> +
committer lyc <yechenli2009@gmail.com> + second commit
 
发现其中;
tree 35592c587f70cf6ec1b99bb382bec2ef92f83396 是本次提交指向的tree对象(即根目录)对应文件是
.git/objects//592c587f70cf6ec1b99bb382bec2ef92f83396
 
parent a3951d57b1413275b171d967fa67fd90eecff648是第二次提交指向第一次提交对象的指针
author和committer分别是作者是提交者
 
再来看 35592c587f70cf6ec1b99bb382bec2ef92f83396文件的内容
$ git cat-file -p 35592c587f70cf6ec1b99bb382bec2ef92f83396
tree 9e7b8054ac3ca530d8e69556dff5903cdcbdc4d3 temp
blob a5bce3fd2565d8f458555a0c6f42d0504a848bd5 test1.txt
这个tree对象也指向一个tree对象和一个blod对象,分别代表temp目录和test1.txt文件的sha1文件
这一行 040000 tree 9e7b8054ac3ca530d8e69556dff5903cdcbdc4d3    temp 的对应文件是
.git/objects/9e/7b8054ac3ca530d8e69556dff5903cdcbdc4d3
 
再继续看tree对象9e7b8054ac3ca530d8e69556dff5903cdcbdc4d3里面的内容
$ git cat-file -p 9e7b8054ac3ca530d8e69556dff5903cdcbdc4d3
blob 180cf8328022becee9aaa2577a8f84ea2b9f3827 test2.txt
文件内容中只有一个指向blob对象的指针(即test1.txt对象的sha1文件),对应的文件为
.git/objects//0cf8328022becee9aaa2577a8f84ea2b9f3827
至此,新增加的4个文件的关系已找到。
 
两次提交的关系如图:
 
 
这就是git的对象系统,本质上是一个key-value的内容寻址文件系统。
当用git add命令把一个文件或者目录添加到git跟踪的时候,会生成一个blob对象或者tree对象
当用git commit 来提交的时候,会创建一个commit对象,commit包含了提交者信息,还包含一个指向仓库根目录的tree对象。
然后tree对象再包含指向文件的blob对象或者子目录tree对象
 
 

git设计哲学的更多相关文章

  1. git database 数据库 平面文件 Git 同其他系统的重要区别 Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异 Git 的设计哲学

    小结: 1.如果要浏览项目的历史更新摘要,Git 不用跑到外面的服务器上去取数据回来 2.注意 git clone  应指定版本,它复制的这个版本的全部历史信息: 各个分支  git init 数据库 ...

  2. 跟vczh看实例学编译原理——一:Tinymoe的设计哲学

    自从<序>胡扯了快一个月之后,终于迎来了正片.之所以系列文章叫<看实例学编译原理>,是因为整个系列会通过带大家一步一步实现Tinymoe的过程,来介绍编译原理的一些知识点. 但 ...

  3. Python的设计哲学探究

    在Python shell中输入import this就会在屏幕上打印出来Python的设计哲学,如下: In [25]: import this The Zen of Python, by Tim ...

  4. Java面向接口编程,低耦合高内聚的设计哲学

    接口体现的是一种规范和实现分离的设计哲学,充分利用接口可以极大的降低程序中各个模块之间的耦合,提高系统的可维护性以及可扩展性. 因此,很多的软件架构设计理念都倡导"面向接口编程"而 ...

  5. Python的设计哲学

    Beautiful is better than ugly. 优美胜于丑陋 Explicit is better than implicit. 明了胜于晦涩 Simple is better than ...

  6. 第八课:不一样的链表 linux链表设计哲学 5星级教程

    这一课最后实现的链表,和普通链表不同,借鉴了linux内核链表的思想,这也是企业使用的链表. 基础介绍: 顺序表的思考 顺序表的最大问题是插入和删除需要移动大量的元素!如何解决?A:在线性表数据元素之 ...

  7. React的设计哲学 - 简单之美

    React最初来自Facebook内部的广告系统项目,项目实施过程中前端开发遇到了巨大挑战,代码变得越来越臃肿且混乱不堪,难以维护.于是痛定思痛,他们决定抛开很多所谓的“最佳实践”,重新思考前端界面的 ...

  8. Python的设计哲学--zen of Python

               Python的设计哲学--zen of Python Beautiful is better than ugly. 优美胜于丑陋 Explicit is better than ...

  9. 理解numpy中ndarray的内存布局和设计哲学

    目录 ndarray是什么 ndarray的设计哲学 ndarray的内存布局 为什么可以这样设计 小结 参考 博客:博客园 | CSDN | blog 本文的主要目的在于理解numpy.ndarra ...

随机推荐

  1. puTTY与SecureCRT的比较

    从网上看到别人对这两个工具的比较:从windows访问linux,除了samba之外,日常操作用得最多的大概就是PuTTY和SecureCRT Putty是免费的,SecureCRT是收费的(当然,有 ...

  2. Windows中APACHE开启fastcgi后无法连接数据库

    环境:Windows server 2003 x64Apache 2.2.14mod_fcgid-2.2b-w32.zipPHP VC9 x86 Non Thread Safe(用Visual C++ ...

  3. OpenGL立方体在世界坐标系中_缩放_旋转_平移_顶点片源着色器_光照作用_棋盘纹理贴图

    读取bmp等图片格式中的像素还有难度,就先用这个棋盘图象素来弄了 代码打错一个就一直First-chance exception ,貌似还有一个要用q或者Q才能成功退出,不知道缺少哪句,我用窗口红叉退 ...

  4. [MarsZ]程序猿谈大学之为什么不推荐就业时做程序猿

    这篇文章适合一切有志做一个程序猿的人,而不仅仅只是即将进入就业市场的大学生. “又到了毕业找工作的时候了,好多朋友打电话向我咨询要不要让孩子做程序员.作为一个业内资深人士,我觉得这不能一概而论!要辩证 ...

  5. nyoj 括号匹配

    这个方程有两种形式,本文采用 if(s[i]=s[j]) dp[i][j]=d[i-1][j-1]   dp[i][j]=min(dp[i][k]+dp[k+1][j],dp[i][j]) (i=&l ...

  6. HTTP的升级产品:SPDY

    一.什么是SPDY? SPDY是Google开发的基于传输控制协议(TCP)的应用层协议 .目前已经被用于Google Chrome浏览器中来访问Google的SSL加密服务.SPDY当前并不是一个标 ...

  7. sql server smo

    在SQL Server2005以前的版本中,SQL分布式管理对象(SQL-DMO)为我们提供了非常有效的方法来通过编程的方式管理SQL Server.SQL-DMO支持基于COM的接口,开发人员可以通 ...

  8. [置顶] 使用U盘安装ubuntu系统

    使用U盘安装ubuntu系统 在网上找了很多教程,都不起效,提示:“从光盘上读取数据出错”. 总结出了几个关键点. 首先,版本,Ubuntu 12.04 Server,一般的U盘安装都会报:“从光盘上 ...

  9. 【Mysql学习笔记】浅析mysql的binlog

    最近读一份关于“数据库事务故障恢复"的技术资料,发现对mysql的binlog的认识不够清楚,查阅mysql reference manual有所收获,作为笔记,记录于此. 1. What' ...

  10. svn无法更新解决方案

    1.删除C:\Documents and Settings\用户名\Application Data\Subversion\auth下的文件,删除svn登录信息. 2.将eclipse中 window ...