前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探秘git隐藏文件夹

探秘git隐藏文件夹

原创
作者头像
mariolu
修改2020-01-06 14:24:26
4.5K0
修改2020-01-06 14:24:26
举报

一、分布式管理

分布式的版本管理同svn集中式版本管理不同的是,本地维护一个版本库,所以不需要联网服务器就可以做开发版本管理。每个开发者对自己仓库拥有写权限,而对其他所有人仓库的读权限。同时有个代表“官方”项目的权威的仓库。

1.1 git的管理文件夹

在工程会有个管理仓库的文件夹.git。这个git保存了版本管理的所有数据。今天就来探秘这个.git文件夹的设计思想。

图1、git仓库文件夹
图1、git仓库文件夹

1.2 git的版本管理基本知识

  • commit:一次对本地仓库的提交。这个提交有个唯一识别id,最长40位,但是使用这个id,只要位数足够可以唯一代表这个commit,就不一定最长到40位。
  • branch/tag:一次仓库的副本,这个副本有一串历史commit,是仓库的另一种快照,tag是仓库的里程碑。处在分支的代码是安全的,否则不在分支的孤立commit可能被git当垃圾清理掉
  • 文件内容变更:变更保存的是内容的差异值
  • 提交历史:每个commit的有依赖父子关系,形成了一串提交历史
  • 本地/远程:本地对应的是本地仓库,并且维护了一个跟远端的关联关系
  • 映射关系:本地仓库和官方远程仓库进行同步,同步的方法:如分支的映射关系、当前提交

1.3 git仓库配置

git clone xxxx 克隆一个远端分支会产生一个./git/config。一个最简config配置如下:

图2、最简config文件配置
图2、最简config文件配置

1.3.1 [core]分区

core存的是与分支无关的配置

  • filemode = true #忽略文件权限变化带来的diff
  • repositoryformatversion = 0, 一种配置风格
  • logallrefupdates = true, #记录所有ref的更新,什么是ref。ref是描述当前仓库所有本地分支,每一个文件名对应相应的分支,文件内部存储了当前分支最新的commit hash值。因此新建分支,只要往.git/refs/heads/分支名写入commit hash值就是这么简单。
  • core.bare=false # 默认不创建裸仓库,裸仓库是创建的仓库并不包含工作区 ,在裸仓库上执行Git 命令,而从裸仓库 clone 下来的本地仓库可以进行正常的 push 操作, 但是从一般仓库 clone 下来的本地仓库却不行。 所以裸仓库一般是作为远端的中心仓库。使用 git init --bare <repo> 可以创建一个裸仓库,并且这个仓库是可以被clone 和 push, 裸仓库不包含工作区,所以在裸仓库不能直接提交变更。

1.3.2 [remote]分区、[branch]分区

[remote "origin"]和[branch "master"]指的是本地如何与远程仓库做交互。

图3、remote配置同git fetch/pull命令的联系
图3、remote配置同git fetch/pull命令的联系

[remote]的url选项指定远程拉取地址,fetch的字符串格式是 “+源分支:目的分支"。比如说例子的fetch = +refs/heads/*:refs/remotes/origin/*,意思是refs/heads/目录下的任意分支最新commit都关联到:refs/remotes/origin/*的同名文件。

[branch]使用remote指定master分支关联到remote/origin分支。merge指定了要merge的源。

这两个配置跟git fetch、git pul命令有关系,这两个命令就是在这个配置找映射关系。比如说

  • git fetch orign会查找.git/config文件中的[remote origin]的配置url,按照fetch规则把最新远端所有的分支的commit id更新到./git/refs/remotes/origin文件夹中。
  • git merge会去找./git/refs/remotes/origin/某个分支,合并到refs/heads/某个分支

二、git目录结构

2.1 refs文件夹(分支管理)

图4、本地分支和远端分支(绿色是当前头指针所在的分支)
图4、本地分支和远端分支(绿色是当前头指针所在的分支)

在refs文件夹存在着3个子文件夹,分别是:

  • .git/refs/heads 本地分支
  • .git/refs/remotes 远端分支,remotes文件夹将所有(比如git remote)命令创建的所有远程分支存储为单独的子目录。在每个子目录中,可以发现被fetch进仓库的对应的远程分支。
  • .git/refs/tags 里程碑分支,描述当前仓库的tag信息,其工作原理与heads一致。
图5、refs目录结构
图5、refs目录结构
图6、refs分支heads和remotes的关联关系
图6、refs分支heads和remotes的关联关系

git branch创建一个分支(git branch tmp),这里其实就是在ref/heads创建一个文件,这个文件内容是个当前commit id。ref是描述当前仓库所有本地分支,每一个文件名对应相应的分支,文件内部存储了当前分支最新的commit hash值。因此新建分支,只要往.git/refs/heads/分支名写入commit hash值就是这么简单。

图7、ref的叶子文件的内容就是一个commit id
图7、ref的叶子文件的内容就是一个commit id

没被关联的分支执行fetch会报错

图8、fetch不到的分支报错
图8、fetch不到的分支报错

2.2 objects文件夹(文件内容管理)

2.2.1 object角色

git定义的object有3种角色:commit、tree、blob。角色类型可以用git cat-file -t <commit id>找到。角色间的关系如下:commit对应一个tree,tree里面可以包含另一个tree,tree的叶子节点是一个blob,blog代表这个文件的某个版本状态。

图9、commit、tree和blob的关系
图9、commit、tree和blob的关系

白色的节点是blob,blob存储存储的是文件的内容,只要文件内容一样是,不管文件名不一样,blob一样的,这是git的一个设计特点。同一个文件有不同的状态,用version区分,tree表示的git当时的一个快照状态。这个状态描述了各个文件的状态。

tree是文件夹,blob是文件

图10、一个merge的例子
图10、一个merge的例子
图11、tree的快照
图11、tree的快照
图12、tree和文件夹的关系
图12、tree和文件夹的关系

2.2.2 objects目录结构

  • objects/ folder存储了对象信息。包括文件内容,提交id,树,和tag里程碑信息。
  • objects/[0-9a-f][0-9a-f] folders

存放文件内容的object,unpacked或者loss 对象,这些对象放在256个子目录。子目录名的前两个字母是commit id的头两个字母,commit id剩下的字符串作为文件名字。

图13、文件夹名字+文件名字=comit ID
图13、文件夹名字+文件名字=comit ID

2.3 hooks文件夹(脚本设置管理)

钩子函数脚本用于自定义一些git命令执行时候触发的脚本

比如commit、applypatch、push、rebase被执行会触发相关脚本。要使这些生效,把文件的sample后缀去掉

图14、命令触发脚本
图14、命令触发脚本

2.4 logs文件夹(日志管理)

logs目录夹存储refs文件夹的改变,这些日志包括commit关联关系、提交人、提交时间等,执行git reflog命令可以管理查看这些log

  • logs/refs/heads/ folder 分支管理
  • logs/refs/tags/ folder tag管理

2.5 pack-refs文件(缓存效能管理)

是个git效能优化的文件,文件包含索引并且压缩object,能达到随机访问对象.

branch和tag的变更(统称为 ref)是每个ref在目录下的(子)目录中存储一个文件$GIT_DIR/refs 。尽管许多分支往往会经常更新,但是大多数tag和某些分支从未更新。当存储库具有成百上千个ref时,这种“每个引用一个文件”的格式既浪费存储空间,又损害性能。pack文件夹正是为了解决这个问题而生。

此命令用于通过将ref存储在单个文件中来解决存储和性能问题 $GIT_DIR/packed-refs。当传统$GIT_DIR/refs目录层次结构中缺少ref时,将在此文件中查找该引用并在找到后使用。

分支的持续commit总是在$GIT_DIR/refs目录层次结构下创建新文件 。有过多ref的存储库的做法是将其ref打包--all一次,并偶尔运行git pack-refs。根据定义,tag是固定的,并且不会更改。branch头将带有首字母pack-refs --all,但只有当前分支head将被解包,而下一个pack-refs(不带--all)将使它们解包。

2.6 objects/info文件夹

存储额外扩展信息

info/exclude用于配置本地分支的 例外文件夹,该文件夹不会被git仓库管理。.和gitignore的区别在于,exclude只在本地分支生效,不会被同步到 远端的repo。

2.7 index文件(暂存区管理)

index是个二进制文件夹,对应着暂存区。暂存区:英文叫stage, 或index。一般存放在 ".git目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。暂存区保存元数据包括时间戳、文件名、SHA id。

图15、暂存区和工作区的关系
图15、暂存区和工作区的关系
图16、仓库示意图
图16、仓库示意图

2.8 头指针相关(HEAD、FETCH_HEAD、ORIG_HEAD等)

  • HEAD记录了当前的头指针所对应的commit id。比如说我们想退回到当前提交的前一个提交,就可以这样方便表示:git reset HEAD^
  • FETCH_HEAD记录了远端获取到的状态。最新从远程分支获取的分支。FETCH_HEAD 文件存储的是远程分支的最新的commit信息。
  • ORIG_HEAD记录了HEAD的状态,比如说要进行一些改变头指针的命令。例如像merge、rebase或reset之類
  • 可以中途恢复到原来HEAD状态
  • MERGE_HEAD:执行merge操作的commit id。比如说交互操作时,用于记住这个merge状态。
  • CHERRY_PICK_HEAD:执行cherry_pick,意义同MERGE_HEAD。
  • 类似的还有BISECT_HEAD,REVERT_HEAD,REJECT_NON_FF_HEAD

2.9 modules文件夹

modules包含了第三方的库,比如一个工程包含了另一个repo

图17、module里面展示了另一个repo
图17、module里面展示了另一个repo

2.10 decription文件

decription用于git在web界面用于搜索

三 git的一些设计思想

git是Linux出自同一作者。git的设计者应用现在编程的很多思想。

头指针:HEAD指针,当前仓库所在的commit位置。

git的gc:清理commit,请求文件object

git的文件管理:一个object代表着一个文件的一种版本。

git的缓存:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、分布式管理
    • 1.1 git的管理文件夹
      • 1.2 git的版本管理基本知识
        • 1.3 git仓库配置
          • 1.3.1 [core]分区
          • 1.3.2 [remote]分区、[branch]分区
      • 二、git目录结构
        • 2.1 refs文件夹(分支管理)
          • 2.2 objects文件夹(文件内容管理)
            • 2.2.1 object角色
            • 2.2.2 objects目录结构
          • 2.3 hooks文件夹(脚本设置管理)
            • 2.4 logs文件夹(日志管理)
              • 2.5 pack-refs文件(缓存效能管理)
                • 2.6 objects/info文件夹
                  • 2.7 index文件(暂存区管理)
                    • 2.8 头指针相关(HEAD、FETCH_HEAD、ORIG_HEAD等)
                      • 2.9 modules文件夹
                        • 2.10 decription文件
                        • 三 git的一些设计思想
                        相关产品与服务
                        文件存储
                        文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档