为了更近一步的学习和理解Git的理念,这一节介绍一下Git中的一些基本概念。

  • 基本概念
  • 对象库图示
  • Git在工作时的概念

一、基本概念:

1、版本库:

    Git的版本库就是一个简单的数据库,其中包含所有用来维护和管理项目的修订版本和历史的信息。

    Git不仅提供版本库中所有文件的副本,还提供了版本库本身的副本。

    Git在每个版本库里维护一组配置值,这个我们在上一篇文章中已经有所提及,比如版本库的用户名和email地址。当把一个版本库进行克隆的时候,会复制文件数据以及其他的一些版本库的元数据,但是不会复制配置设置

    Git维护两个主要的数据结构:对象库和索引。所有这些数据都存放在.git隐藏目录内。

2、Git对象类型:

    对象库包含原始数据文件、所有的日志消息、作者信息、日期、以及其他用来重建项目任意版本或分支的信息。

    Git放在对象库里的对象只有4种类型:块(blob)、目录树(tree)、提交(commit)、标签(tag)

    A、块:

         文件的每一个版本被表示为一个blob。一个blob保存一个文件的数据,但不包含任何关于这个文件的元数据,甚至文件名。

    B、目录树(tree):

        一个目录树对象代表一层目录信息。它记录了blob标识符、路径名和在一个目录里所有文件的一些元数据。

    C、提交(commit):

        一个提交对象保存版本库中每一次变化的元数据:作者、提交者、提交日期、日志消息。每一个提交对象指向一个目录树对象,除了根提交,大多数提交都有一个父提交。

    D、标签(tag):一个标签对象分配一个任意的可读的名字给一个特定对象(通常是一个提交对象)。

3、索引:

    目前来说,感觉这个概念不太好解释。

    索引是一个临时的、动态的二进制文件,它描述整个版本库的目录结构。

    我的认识是,索引是介于工作区和对象库之间的一个缓冲区。工作区里的变化会最早在这里有所体现,最后由索引将所有的变动提交到对象库中。

4、可寻址内容名称:

    Git对象库被组织及实现为一个内容寻址的存储系统。对象库中的每一个对象都有一个唯一的名称,这个名称是向对象的内容应用SHA1得到的散列值。

5、Git追踪内容:

    首先,Git追踪的是基于对象内容计算出的散列值,而不关心文件名或目录名。如果两个文件的内容相同,那么不管是否在同样的目录,Git在对象库中只保存一份blob形式的内容副本。

    其次,当文件从一个版本变到下一个版本的时候,Git的内部数据库会有效的存储每一个文件的每个版本,而不仅仅是差异。

    当然,你或许已经发现,上面说的这种存储方式效率很低,因为每一个都要保存副本。这个会在后面打包文件的地方进行说明。

6、路径名和内容:

    Git仅仅记录每个文件名,并且确保能通过它的内容精确的重建文件和目录。

    好吧。。。我还是感觉无法理解作者的意思。

7、打包文件:

    回到上面提出的问题:直接存储每个文件每个版本的完整内容是否太低效了?

    Git使用了一种叫做打包文件的存储机制。要创建一个打包文件,Git首先定位内容非常相似的全部文件,然后为它们之一存储整个内容。之后计算相似文件之间的差异并且只存储差异。


二、对象库图示:

    先来张图压压惊。。。通过这张图看看对象库中的各个对象是如何协作形成整个系统的。

  • blob对象是数据结构的底端,它什么也不引用,且只被树引用。上图中,每个blob对象都用一个矩形来表示。
  • 树对象指向若干个blob对象,也可以指向其他树对象。许多不同的提交对象可能指向任何给定的树对象。
  • 一个圆圈代表一个提交对象,每个提交对象都要指向一个树对象,并且这个树对象是由该提交对象引入到版本库中的。
  • 每个标签最多可以指向一个提交对象。
  • 分支并不是一个基本的Git对象,但是它在命名提交对象的时候有至关重要的作用。

下面我们让对象库变得复杂一些。保留原来的两个文件不变,添加一个包含一个文件的新目录到版本库中。对象图如下:

这里因为顶级目录被添加的新子目录改变了,所以顶级树对象的内容也就跟着改变了。所以Git引入了一棵新的树cafed00d。

树cafed00d依旧引用了原来的两个文件的blob对象,同时新增了一个指向新子目录的树对象。

上面的图是所有Git操作诸如add,commit等全部结束后的对象库整体图,可是我们可能更想知道以下问题:

  • 新子目录的树对象是何时创建的?
  • master分支为何指向了新的提交对象?
  • 新提交的文件对应的blob对象是何时由谁来创建的?

后面的章节会依次说明上述问题。


三、Git在工作时的概念:

1、进入.git目录:

我们新建一个新的版本库,逐步查看一下每次操作后.git目录中会发生哪些变化:

首先,我们创建一个空的版本库。

我们可以看到,除了几个占位符外,.git/objects目录下是空的:

[root@flower1 test]# find .git/objects/
.git/objects/
.git/objects/pack
.git/objects/info

现在,我们创建一个简单的文件,并添加到对象库中。

[root@flower1 test]# echo "hello world" > hello.txt
[root@flower1 test]# git add hello.txt

接下来,我们看一下objects目录下发生的变化:

[root@flower1 test]# find .git/objects/
.git/objects/
.git/objects/3b
.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
.git/objects/pack
.git/objects/info

2、对象、散列和blob:

    从上面的例子里,我们看到,当为hello.txt创建一个对象的时候,Git并不关心hello.txt的文件名。Git只关心文件里的内容。Git对这个blob执行一些操作,计算它的SHA1散列码,并散列码的十六进制表示作为文件名放进对象库里。

    其实上述文件的散列码是3b18e512dba79e4c8300dd08aeb37f8e728b8dad。

    Git将散列码的前2个字符作为一级目录名,可以提高文件系统的效率,相当于将不同对象散列到了不同的文件夹下,避免某个文件目录下文件过多。

    我们可以使用下面命令使用散列码将文件的内容提出出来:

[root@flower1 test]# git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
hello world

   当然,手动收入长度为40的散列码很不切实际,所以Git提供了下面的方式:通过对象的唯一前缀来查找对象的散列值。

[root@flower1 test]# git rev-parse 3b18
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
[root@flower1 test]# git rev-parse 3b18e
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
[root@flower1 test]# git rev-parse 3b18e5
3b18e512dba79e4c8300dd08aeb37f8e728b8dad

我测试的结果是,前缀最少要达到4位才可以。

3、文件和树:

通过上面的演示,我们看到代表hello world的blob对象已经存放到对象库中了。那么它的文件名又发生了什么事呢?

Git通过另一种叫做目录树的对象来跟踪文件的路径名。当使用git add命令时,Git会给添加的每个文件的内容创建一个对象,但不会马上为树创建一个对象。

此时,索引更新了。索引位于.git/index中,它跟踪文件的路径名和相应的blob。每次执行命令时,Git会用心的路径名和blob信息来更新索引。

任何时候,都可以从当前索引创建一个树对象,只要通过底层的git write-tree命令来捕获索引当前信息的快照就可以了。

当前,该索引只包含一个文件:

[root@flower1 test]# git ls-files -s
100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0 hello.txt

从上面的打印信息,可以看到文件的关联,hello.txt和3b18e512…的blob。

接下来我们捕获索引状态并把它保存到一个树对象里:

[root@flower1 test]# git write-tree
68aba62e560c0ebc3396e8ae9335232cd93a3f60
[root@flower1 test]# find .git/objects/
.git/objects/
.git/objects/3b
.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
.git/objects/68
.git/objects/68/aba62e560c0ebc3396e8ae9335232cd93a3f60
.git/objects/pack
.git/objects/info

现在有2个对象:3b18e5的hello world对象和68aba6的树对象。

我们也可以看看树对象里面的内容到底是什么:

[root@flower1 test]# git cat-file -p 68ab
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad hello.txt

4、树层次结构:

    该节通过创建一个新的子目录来看看Git是如何处理多个层次的目录结构的:

[root@flower1 test]# pwd
/root/test
[root@flower1 test]# mkdir subdir
[root@flower1 test]# cp hello.txt subdir/hello.txt
[root@flower1 test]# git add subdir/hello.txt
[root@flower1 test]# git write-tree
492413269336d21fac079d4a4672e55d5d2147ac
[root@flower1 test]# git cat-file -p 492413
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad hello.txt
040000 tree 68aba62e560c0ebc3396e8ae9335232cd93a3f60 subdir

可以看到subdir的树对象和之前的顶级目录树对象时完全一样的。

5、提交:

之前已经通过git add命令添加了hello.txt文件,并通过git write-tree命令生成了树对象。

用下面的底层命令创建一个提交对象:git commit-tree SHA1

[root@flower1 test]# echo -n "Commit a file" | git commit-tree 492413269336d21fac079d4a4672e55d5d2147ac
204fa4469c1642cb9190048ebdc8fabc9a4a4af1

提交对象包含以下信息:

  • 标识关联文件的树对象的名称
  • 创作新版本的人的名字和创作的时间
  • 把新版本放到版本库的人的名字和提交的时间
  • 对本次修订信息的说明(提交信息)

6、标签:

    有2种基本的标签类型:轻量级的和带附注的。

    轻量级标签只是一个提交对象的引用,通常被版本库视为是私用的。这些标签并不在版本库里创建永久对象。

    带附注的标签会创建一个对象。

    可以通过git tag命令来创建一个带有提交信息、带附注切未签名的标签:

[root@flower1 test]# git tag -m "Tag version 1.0" V1.0 204fa

Git版本控制管理学习笔记3-基本的Git概念的更多相关文章

  1. Git版本控制管理学习笔记4-文件管理和索引

        可以认为使用Git时,我们会遇到3个空间:工作目录.索引.版本库.我们关心的,就是在新建.修改等操作时,这三者之间发生了怎样的变化.     笼统的讲,就是在工作目录下编辑,在索引中积累修改, ...

  2. Git版本控制管理学习笔记2--起步

    首先确保系统中已经安装了git,这里使用的linux系统. 一.命令行初步使用: 1.git命令: 列出它的选项和最常用的子命令.标准命令格式中,COMMAND代表的就是下面列出的子命令. [root ...

  3. Git版本控制管理学习笔记1-介绍

    几乎所有的版本控制工具都是出于同样的目的:开发以及维护开发出来的代码,方便读取代码的历史,记录所有的修改.这里,介绍的是当前在开源社区内非常流行的版本控制工具Git.它是由Linus Torvalds ...

  4. Git版本控制管理学习笔记5-提交

        这个标题其实有些让人费解,因为会想这个提交是动词还是名称?     提交动作是通过git commit命令来实现的,提交之后会在对象库中新增一个提交对象.提交过程中会发生哪些变化,在上一篇笔记 ...

  5. Git 版本控制工具(学习笔记)

    GIT(分布式) 一.Git 初始版本控制工具 1. 安装Git Ubuntu系统下,打开shell界面,输入: sudo apt-get install git-core  之后回车输入密码,即可完 ...

  6. Git权威指南学习笔记(二)Git暂存区

    例如以下图所看到的: 左側为工作区,是我们的工作文件夹. 右側为版本号库,当中: index标记的是暂存区(stage),所处文件夹为.git/index,记录了文件的状态和变更信息. master标 ...

  7. Git与GitHub学习笔记(八)git如何同时同步提交到码云和GitHub上

    前言: 今天github push代码一直push不上去,打算就备份一份代码带国内开源码云上. Github容易出现的情况是: 国内访问速度比较慢, 如果被墙掉的话,就直接没发使用了 如果开源个PHP ...

  8. C++内存管理学习笔记(5)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  9. C++内存管理学习笔记(6)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

随机推荐

  1. JVM内存分配策略

    在 JVM内存垃圾回收方法 中,我们已经详细讨论了内存回收,但是,我们程序中生成的对象是如何进行分配的呢?以下所述针对的是HotSpot虚拟机. 1.Java堆结构 以HotSpot为例,如下图: H ...

  2. 7Hibernate高级----青软S2SH(笔记)

  3. coreseek增量索引

    1.在多数情况下,因为Coreseek索引速度高达10MB/s,所以只需要创建一个索引源即可满足需求,但是在数据量随时激增的大型应用中(如SNS.评论系统等),单一的索引源将会给indexer造成极大 ...

  4. ActiveMQ集群下的消息回流功能

    ------------------------------------------------------------------ "丢失"的消息 如果有broker1和brok ...

  5. 【学习笔记】Struts2之配置处理结果

        Action只是Struts2控制器的一部分,所以它不能直接生成对浏览者的响应.Action只负责生成响应的视图组件,通常是JSP页面,而Action会为JSP页面提供显示数据.     Ac ...

  6. 移动Web之响应式布局的探讨

    响应式布局的探讨 响应式布局的两种方式 基于百分比的布局 例:Bootstrap 基于rem的布局 例:淘宝触屏版 这两种布局都需要依赖于CSS3的media query来设置布局断点(或者通过js监 ...

  7. asp.net mvc使用log4gNetz

    1. 下载安装log4gNet 2. 将 \bin\net\4.0\release\log4net.dll 复制到你的项目中 . 3. 将log4net.dll 添加引用到你的项目中. 4. 添加如下 ...

  8. java从基础知识(十)java多线程(上)

    线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元.另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点 ...

  9. sublime3的安装和插件之类的

    1.http://www.sublimetext.com/3 选择适合自己电脑的下载 2.下载完之后打开,help -> enter lisence 谷了下注册码如下,粘贴过去,万一不行请自由飞 ...

  10. SEO之title优化

    作者:andyrat,联系方式:andyrat@qq.com