GIT原理个人理解

GIT原理的个人理解

        只要在编程圈混过的人肯定使用或者至少听说过git和github,其重要性不言而喻。我们知道git可以很方便的管理代码,常用的命令也不是很多,很容易记住。但是对于想要在编程圈扎根的Coder来说,仅仅停留在会使用一些简单命令是远远不够的,知其然还要知其所以然,所以对git原理进行探究还是很有必要的。

git是什么?

        git是一个分布式版本控制系统,所谓的版本控制系统(VCS),就是为了控制和协调各个版本的文档内容或代码,便于文档或代码恢复至历史的任何一个版本或状态。版本控制系统分为集中式和分布式,集中式就是把代码的管理和同步放在同一个服务器来进行,分布式是把集中式版本控制系统的服务端和客户端都交给参与开发的客户端来保管,只有需要不同开发者合并代码时,才需要一个中转站来完成,非常适合异地多人协作。

git原理

三个重要对象

  首先需要搞清楚git中有三个非常重要的对象,分别是Blob对象、tree对象和commit对象。Blob对象保存的是文件的内容,tree对象相当于一个文件夹,可以包含多个Blob对象和tree对象;想要获得完整的某一历史版本,需要知道各文件和文件夹的SHA-1校验和(校验和后面会解释),但是没有作者,何时、为什么提交这些快照,commit对象正是为了解决这一问题,commit对象包含了一个顶层tree对象(其实就是一个SHA-1校验和,通过该校验和就可以获得完整的历史版本)、提交者信息(可以通过git config设置)、提交的时间戳、一个空行和提交注释信息。

        其实可以将这三个对象的关系看成是一个树形关系,Blob对象可以看成是叶节点,tree对象可以看成是中间节点,commit对象可以看成是根节点,它们通过指针(SHA-1校验和)进行关系的连接,通过根节点可以找到任一个子节点(tree对象和Blob对象)。

校验和

        git能够获得提交的任一历史版本,说明每次提交都是对项目文件的完整拷贝,这样有些人肯定会疑惑,既然每次提交都是对项目文件的完整拷贝,那么git的占用空间不是随着提交次数的增加而线性增加吗?没错,相比于其他版本控制系统的增量存储,git的快照技术存储确实使得存储空间增大了,但是增量存储在进行文件合并时非常耗时,而快照技术不需要文件的合并,直接改变指针的指向即可,所以加载速度很快。所谓的快照,实际上就是SHA-1校验和。SHA-1校验和,它是一个40个字符长度的校验和,如:5453545dccd33565a585ffe5f53fda3e067b84d8,该校验和是根据文件内容算出来的,只要文件有一丢丢的不一样,那么计算出来的SHA-1校验和也是不一样的,SHA-1校验和不是为了文件加密,而是为了保证获取的任一历史版本都是完整的。每次提交时git的处理是这样的:若是文件发生了变化,哪怕一丢丢变化,都会生成新的文件(是完整的内容,而不是变化的内容)和SHA-1校验和,若是文件没有变化,则只是简单的拷贝文件的SHA-1校验和,提交某一个版本时,仅仅是提交了指针(SHA-1校验和)间的相互的关系,每一个指针都指向一个commit对象或tree对象或Blob对象。

分支和引用

        分支是git的杀手级特征,它极大地方便了开发者的开发工作,比如你正在开发一个项目,突然老板交给你一个新活,让你调试一个bug,这时你不会放弃手头的任务转向老板的任务吧?其实我们可以新建一个分支用来进行bug的修改,主分支仍然进行现有项目的开发。

        首先,谈谈引用,所谓引用,就是SHA-1校验和的别名,因为SHA-1校验和的长度为40位,难以记住,所以用引用来帮助人们,引用存储在.git/refs中。分支实际上就是一个引用,该引用存储在.git/refs/heads/文件夹中,新建一个分支就在该文件夹下新建一个文件,该文件存储着SHA-1校验和。git的默认分支是master,它始终指向项目主分支的最后一次提交记录。.git文件夹下有个非常重要的文件HEAD,该文件指向当前分支的引用,该文件并没有存储着SHA-1校验和,而是存储着当前文件的路径,如.git/refs/heads/branchName。当执行git commit时,就创建了一个commit对象,并把commit对象的父级设置为HEAD指向的引用,即当前分支(一个40位的SHA-1校验和)。当执行git checkout branchName切换分支时,仅仅是将HEAD文件中存储的路径改变,非常方便。

分支的合并

        创建git分支非常的简单,那么合并分支呢?实际上合并分支也非常简单。分支的合并主要分为两类,第一类是没有出现分叉,第二类是出现了分叉。

        第一类,commit提交树没有出现分叉。以下图片均来自网络。
没有分歧

        这种情况比较简单,我们只需要将maaster分支简单地向前移动到dev分支处,这种情况并不需要处理分歧,非常快,称为快进(Fast Forward)。

        第二类,commit提交树出现分叉。
出现分歧

        对于这类情况,有两种方法进行分支的合并,merge和rebase。

        merge方法是这样的:基于master分支指向的v7、dev分支指向的v5和共同祖先v3,进行三方合并计算,得到新的版本v8,之后将master移动指向v8即可。
merge

        rebase方法是这样的:基于分支的最近的共同祖先v3,根据当前分支的历代提交对象(v4,v5),生成一系列补丁文件,然后以master分支的最后一次提交对象(v7)为新的出发点,逐个应用之前的补丁文件,生成新的合并提交对象(v4’、v5’),从而改写dev分支的提交历史,之后便是第一类情况。rebase和merge相比,提交历史更加整洁。
在这里插入图片描述

git工程

.git工程目录

        .git的工程如下图,其中重要的文件和文件夹有:objects文件夹,存放对象;refs文件夹,存放引用,其中refs/heads存放git工程拥有的分支文件;HEAD文件,存储当前分支的引用;config文件,存储当前仓库的配置信息。

在这里插入图片描述

git工作区域

        git工作区域有三个,分别是工作区、暂存区和本地仓库。工作区就是程序猿们写代码调试的地方;本地仓库是代码提交到的地方;暂存区可能比较难以理解,可能有些人觉得暂存区没有必要存在,其实暂存区的存在极大地方便了代码的提交,比如你正在开发项目的两个功能A和B,A功能已经完成,需要提交,但是B功能还未完成,你不想提交,这时可以将A功能的添加到暂存区,B功能不添加到暂存区,便可以将A和B功能分开提交。

        git文件的状态有untracked、staged、modified、unmodified。

在这里插入图片描述


        下面对这四种状态进行详细的解释说明。

        关于untracked状态。当在.git工程中新建一个文件,该文件未被git标记跟踪,为untracked状态,其他情况都不会是untracked状态。

        关于staged状态。当用git add将文件添加到暂存区后,文件状态便变为staged,表示已添加到暂存区但是还未提交。

        关于unmodified状态。当用git commit将暂存区文件提交到本地仓库后,文件状态便变为unmodified,表示文件和本地仓库文件相比未变化。

        关于modified状态。将暂存区文件提交到本地仓库后,此时文件为unmodified,若之后对文件再进行修改的话,文件状态便变为modified,表示与本地仓库相比,文件已发生变化。

参考文献

Git的核心概念

GIT文件四种状态

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值