首页 > 其他分享 >git原理性概念

git原理性概念

时间:2024-03-04 22:02:36浏览次数:23  
标签:git hash ljc object tree 概念 原理 commit

参考资料

近期学习git内部概念及原理,为了加强效果和日后回忆,还是写了这篇笔记进行输出。

参考资料如下:

实验环境:unbuntu 18

objects(blobs tree commits tag) & hash

git里的object 有四种:tree object 、 blob(Binary Large Object) object、 commit object、 tag object

git 会为每个object生成一个SHA1哈希码作为“身份证”。

在git仓库中添加一个文件,git将创建一个blob object对应这个文件。

git的blob object内容与文件内容相关,而与文件名无关。git将对文件的内容使用SHA1哈希算法,产生一串哈希码。该哈希表唯一标识该文件与其对应的object

文件的路径名(pathname)等信息,由tree object 存储。其组织方式类似于Linux文件组织方式。

每一次commit都会产生一个commit object,同样有hash码对应每次commit

只要文件内容相同,blob object的hash就是相同的,因为hash码只对文件内容起作用。

文件内容相同,且文件组织方式也相同时,tree object的hash码才会相同。

commit object的hash码很难相同,因为除了文件内容,提交人的name、email、提交时间等信息都会参与到hash码的计算中

tag则用来引用(reference)一个commit,分为lighweight 和 annotated tag。前者不会创建object,后者则会创建object。许多git命令都只对后者有效。同样的,tag object也会对应一个hash码。

working directory、index、object store/repository(工作区、暂存区、仓库)

注意:在repository的内容不能被删除或修改,只能添加!

  • working directory 存放工作linux目录中的内容

  • index(暂存区)存放一种“索引”,记录目录之间的关系,通常git add 命令会修改该索引,git commit则会将“索引”转换为tree object存储在仓库中

  • object store(仓库)存放4中object,各个object都有hash码与其对应,git commit将会在这个区域中增加object,但不会修改\删除object

先新建一个文件夹,初始化为一个git仓库

ljc@ljc:~/gitlearning$ mkdir project
ljc@ljc:~/gitlearning$ cd project/
ljc@ljc:~/gitlearning/project$ git init
Initialized empty Git repository in /home/ljc/gitlearning/project/.git/
ljc@ljc:~/gitlearning/project$ ll
total 12
drwxrwxr-x 3 ljc ljc 4096 3月   1 19:37 ./
drwxrwxr-x 4 ljc ljc 4096 3月   1 19:37 ../
drwxrwxr-x 7 ljc ljc 4096 3月   1 19:37 .git/

初始化后添加文件、提交文件

在这之前,可以先了解一下git ls-file 和 git cat-file命令:

git-ls-files - Show information about files in the index and the working tree
git-ls-files -s #展示被staged的file对象的哈希值等信息

git cat-file -p <对象哈希码>  # 可该哈希码对应的object的具体内容
git cat-file -t <对象哈希码>  # 可查看

初始化

新建一个project文件,使用git init初始化git仓库

image-20240301193904642

观察.git/objects文件夹, 目前发现只有info、pack这两文件夹

image-20240301194919345

添加两个文件,分别写入内容“foo” “bar”,使用git status可知晓这两个文件目前还没有加入暂存区

image-20240301195213458

目前,index区(暂存区)和object store中没有任何东西

image-20240301195532209

git add 后

将两个文件staged,可以观察到,.git/objects目录下,多出两个blob object,分别对应file1和file2,说明此时两个file对应的object已经被存储

image-20240301202138713

途中这一连串的十六进制码就是object对应的哈希码。且他们的内容存储于.git/objects目录下,为了防止文件数目过大,采用了层级式目录的方式存储object,取hash码的前两个字符先创建一个子目录,然后在子目录中存储对应的object:

image-20240301203432721

且在index也已经创建出了某个index,指向了这两object。由于index没有对应的object,因此不能在.git/objects目录下看到对应的变化。但可以观察./git目录,发现多出来一个index文件,猜想这个文件就对应着Index区。

image-20240301201138500

那么目前三个区域的内容如下所示:

image-20240301203804274

git commit 后

最后commit这两个file:

image-20240301204218591

此时,./git/objects 中会出现两个新的object

image-20240301204404999

使用git cat-file -p查看这两个object类型:

image-20240301204524493

可以发现,其中一个是commit object和一个tree object。

因为git commit后会将index转化为tree object,然后生成一个commit object“指向”该tree object。此时,三个区的内容如下:

image-20240301205305673

看看tree object 和 commit object的内容

image-20240301205911661

tree object像一个文件目录一样把其中的文件关系记录下来。commit object则存储了提交者的信息以及提交信息。

分支

创建分支

创建分支不会产生任何object,分支名只是一种引用,指向了某个commit,它会在.git/refs/heads中。

下面创建分支branch1:

image-20240304170037243

使用git cat-file -p 命令查看他们的内容

image-20240304170409097

看到它们的输出与commit object的输出相同,但它们并不是object本身,因此可以将它们视作一种引用。而且,目前在branch1分支与master分支的指向是相同的,目前的存储区域内容如下所示,几乎没有任何影响。

image-20240304171042772

分支中进行commit

image-20240304191806926

此时object store中将加入三个新的object,分别为blob object、 tree object和commit object。

存储区域的内容变更如下图:

image-20240304193744092

git不会修改object store中的内容,因此即使在working directory中的某些文件被修改,git会直接创建另一个blob object并重新计算哈希值,且将index的引用至新的blob object上。

当commit时,先将index转化为新的tree object(对应hash值为abd31),然后创建一个commit object(对应hash值为d14e3)使其引用新的tree object。

合并分支

这里不考虑复杂的合并情况,也不考虑合并冲突的情况。但为了不至于太简单,首先切回master分支,然后在file2中新加上一行内容,最后commit该改动。

image-20240304202331875

此时,两个分支中的4个文件内容分别为:

image-20240304202607930

在master分支上,执行git merge合并branch1:

image-20240304202945834

git会自动生成commit object来执行这次的merge:

image-20240304203108826

存储区域的内容变更如下图:

image-20240304204739565

标签:git,hash,ljc,object,tree,概念,原理,commit
From: https://www.cnblogs.com/HeyLUMouMou/p/18052827

相关文章

  • 使用Git拉取并运行vue项目
    从远程仓库中拉取vue项目。一、复制项目在远程仓库的代码地址,将它克隆到本地:gitclonehttp链接(项目代码地址)二、安装依赖1.进入项目所在的目录,将node_modules和package-lock.json2.选中当前路径,然后输入【cmd】,回车3.在命令提示符中依次输入一下代码:npmcacheclean-fo......
  • 新零售SaaS架构:订单履约系统的概念模型设计
    订单履约系统的概念模型订单:客户提交购物请求后,生成的买卖合同,通常包含客户信息、下单日期、所购买的商品或服务明细、价格、数量、收货地址以及支付方式等详细信息。子订单:为了更高效地进行履约,大订单可能会被拆分成多个子订单,子订单会根据商品类型、配送地址、仓库位置或......
  • git - 查看部分log
    这是个gitlog的例子,后面都用这个例子➜qverse_managementgit:(develop)gitlog--oneline|head79ebea4Mergebranch'feature/3.2.5'into'develop'b0a3714fix:时间过滤不管用c5f7212fix:关联列表检索fe767a6fix:绘制规则默认关闭55a6a65fix:没有配置绘制规......
  • git - 揪出来改你代码的人
    先查找某个文件的历史修改记录,然后根据关键信息匹配对应的更改,根据具体情况显示更改的前N行,就能查到commit信息了!比如我要查看是谁删掉了我requirements.txt文件的这行代码openpyxl==3.1.2执行下面的命令就查到commit信息了➜e100_v2git:(3.3/dev)gitlog-p--requi......
  • TortoiseGit使用问题总结
    1、安装和汉化https://blog.csdn.net/qq_42889406/article/details/1087633882、基本使用和克隆https://zhuanlan.zhihu.com/p/3818512073、TortoiseGitPlink提示输入密码https://blog.csdn.net/lala1583165/article/details/108277387......
  • git diff去除^M的方法
     在使用Git进行版本控制时,有时候会遇到在文件中出现了^M字符的情况。这个问题通常出现在Windows操作系统中,并且会影响文件在不同操作系统之间的可移植性。^M字符是回车符的表示,在Windows操作系统中,每个文本行的结尾都是由回车符(\r)和换行符(\n)组成的,而在类Unix......
  • BOSHIDA DC电源模块的工作原理及应用
    BOSHIDADC电源模块的工作原理及应用DC电源模块是一种常见的电子元件,它具有将交流电转换为直流电的功能。在很多电子设备中,尤其是需要稳定的直流电源供应的设备中,DC电源模块被广泛应用。 DC电源模块的工作原理可以简单描述如下:将输入的交流电转换为直流电。首先,交流电输入到......
  • git常用命令
    1、创建仓库和配置仓库#初始化仓库gitinitgitadd.gitcommit-m"initcommit"gitremoteaddorigin<https://...>gitpush-uoriginmaster#查看git用户名和邮箱gitconfiguser.namegitconfiguser.email#设置全局用户名和邮箱gitconfig--globaluser.......
  • vue2响应式原理
    Vue.js是一个流行的JavaScript前端框架,它的核心特性之一就是响应式数据绑定。Vue.js2.x版本的响应式原理主要基于Object.defineProperty函数来实现。Vue.js的响应式原理大致可以描述为以下几个步骤:数据劫持:当Vue实例创建时,Vue会遍历data选项中的属性,并使用Obje......
  • Git 使用
    更新改动的代码到仓库gitadd.gitcommit-m"24-03-04:ignorefile"gitpushoriginmaster拉取不同版本gitloggitcheckout35d2c50c8655ca04c8ba10f3fc91b69247f38632.gitignore规则不生效.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入......