.git目录

下面就开始进入.git目录,通过“ls”命令可以看到.git目录中的文件和子目录:

对于这些文件和目录,下面给出了一些基本的描述。

  • hooks:这个目录存放一些shell脚本,可以设置特定的git命令后触发相应的脚本;在搭建gitweb系统或其他git托管系统会经常用到hook script
  • info:包含仓库的一些信息
  • logs:保存所有更新的引用记录
  • objects:所有的Git对象都会存放在这个目录中,对象的SHA1哈希值的前两位是文件夹名称,后38位作为对象文件名
  • refs:这个目录一般包括三个子文件夹,heads、remotes和tags,heads中的文件标识了项目中的各个分支指向的当前commit
  • COMMIT_EDITMSG:保存最新的commit message,Git系统不会用到这个文件,只是给用户一个参考
  • config:这个是GIt仓库的配置文件
  • description:仓库的描述信息,主要给gitweb等git托管系统使用
  • index:这个文件就是我们前面提到的暂存区(stage),是一个二进制文件
  • HEAD:这个文件包含了一个档期分支(branch)的引用,通过这个文件Git可以得到下一次commit的parent
  • ORIG_HEAD:HEAD指针的前一个状态

Git引用

Git中的引用是一个非常重要的概念,对于理解分支(branch)、HEAD指针以及reflog非常有帮助。

Git系统中的分支名、远程分支名、tag等都是指向某个commit的引用。比如master分支,origin/master远程分支,命名为V1.0.0.0的tag等都是引用,它们通过该保存某个commit的SHA1哈希值指向某个commit

重新认识HEAD

HEAD也是一个引用,一般情况下间接指向你当前所在的分支的最新的commit上。HEAD跟Git中一般的引用不同,它并不包含某个commit的SHA1哈希值,而是包含当前所在的分支,所有HEAD直接执行当前所在的分支,然后间接指向当前所在分支的最新提交。

为了更形象的解释上面的描述,我们首先查看“.git/HEAD”的内容:

这就表示HEAD是一个指向master分支的引用,然后我们可以根据引用路径打开“refs/heads/master”文件,内容如下:

根据前面一片文章的介绍,我们通过这个哈希值查看对象的类型和雷人,可以看到这个哈希值对应着一个commit,并通过“git log”可以发现这个commit就是master分支上最新的提交。

所以可以看到,所有的内容都是环环相扣的,我们通过HEAD找到一个当前分支,然后通过当前分支的引用找到最新的commit,然后通过commit可以找到整个对象关系模型,看下图:

引用和分支

直到现在我们都没有开始介绍分支(branch),先大概展示一下引用和分支的关系。

假设我们现在除了master分支,又创建了一个release-1.0.0.1的分支,再次查看“.git/refs/heads/”目录,可以看到除了master文件之外,又多了一个release-1.0.0.1文件,查看该文件的内容也是一个哈希值。

通过“git show-ref --heads”命令就可以查看所有的头,这些都是HEAD的候选值:

HEAD文件的内容是commit的分支,当我们把分支切换到release-1.0.0.1的时候,HEAD文件的内容也会相应的变成:

ref: refs/heads/release-1.0.0.1

日志

我们进入“.git/logs”文件夹,可以看到这个文件夹也有一个HEAD文件和refs目录,这些就是记录commit历史记录的地方。我们可以通过commit的哈希值,把repo退到一个指定的状态。

Git索引index

前面文章我们也提到过index/stage,就是更新的暂存区,下面来看看index文件。

index(索引)是一个存放了已排序的路径的二进制文件,并且每个路径都对应一个SHA1哈希值。在Git系统中,可以通过“git ls-files --stage”来显示index文件的内容:

从命令的输出可以看到,所有的记录都对应仓库中的文件(包含全路径)。上面显示的哈希值就是abc.txt的blob对象的哈希值。

现在我们更新abc.txt文件,并通过“git add”添加到暂存区,这时发现index中的abc对象的哈希值已经变化了。

对象的存储

前面提到所有的Git对象都会存放在“.git/objects”目录中,对象SHA1哈希值的前两位是文件夹名称,后38位作为对象文件名。下面是之前提到的master最新的commit对象的哈希值:

63a6ea8475b47078dee14ea8ff2c8731927ffbbf

在Git系统中有两种对象存储的方式,松散对象存储和打包对象存储

松散对象(loose object)

松散对象存储就是前面提到的,每一个对象都被写入一个单独文件中,对象SHA1哈希值的前两位是文件夹名称,后38位作为对象文件名。

打包对象(packed object)

对应松散存储,把每个文件的每个版本都作为一个单独的对象,它的效率比较低,而且浪费空间。所以就有了通过打包文件(packfile)的存储方式。

Git使用打包文件(packfile)去节省空间。在这个格式中,Git只会保存第二个文件中改变的部分,然后用一个指针指向相似的那个文件。

一般Git系统会自动完成打包的工作,在已经发生过打包的Git仓库中,object/pack目录下回成对出现很多“pack-***.idx”和“pack-***.pak”文件。

最新文章

  1. Java高效编程之四【C语言结构的替代】
  2. 【iOS】环形渐变进度条实现
  3. iOS - UIScrollView
  4. C++ string 构造的陷阱
  5. ajax_get方式
  6. Ubuntu16.04安装GTK3主题:OSX-Arc
  7. Mysql中让两个字段不同时相同的方法
  8. 循环渐进linux笔记——linux系统基本机构
  9. Python开发:Python2和Python3的共存和切换使用
  10. Hibernate入门(十)inverse
  11. cors解决跨域
  12. Android数据存储:SQLite
  13. Linux修改hostname时/etc/hosts、/etc/sysconfig/network ,hostname,三者的区别和联系
  14. MyBatis insert操作返回主键
  15. Docker基础教程(安装篇)
  16. RV32M指令集
  17. css之-webkit-scrollbar
  18. linux平台程序高精度延时问题select-usleep等
  19. Kafka迁移与扩容工具用法
  20. mysql having,group by查询去除重复记录

热门文章

  1. ScriptManager和ClientScript的区别
  2. Unity 逐步旋转
  3. UVA 393
  4. HDU1518 Square(DFS,剪枝是关键呀)
  5. Reids 主从同步
  6. Codeforces Round #250 (Div. 2) C、The Child and Toy
  7. 【BZOJ2190】【SDOI2008】仪仗队
  8. Android -- 滑式抽屉SlidingDrawer(非原创)
  9. Linux之网络配置(不断更新中)
  10. C语言中常量