计算机基础——Git的底层原理,reverse和reset的区别,rebase作用

Posted iaiti

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机基础——Git的底层原理,reverse和reset的区别,rebase作用相关的知识,希望对你有一定的参考价值。

目录

 

1、分区

2、对象

3、对象实例演示

4、branch和tag

5、reset和reverse区别

6、rebase作用

7、rebase再探究竟,rebase和merge区别


 

这一篇其实不属于计算机基础的,但是随着大家平时工作还有开源一些项目的版本控制的使用,使用叫多的git。
回过头来,有时在思考reverse和rebase区别,回归到底层的一些原理的时候,就有茅塞顿开的感觉了。

1、分区

首先Git有分三个区,工作区,暂存区和版本库。

2、对象

Git当中一共有3种主要的对象:blob,tree,commit


git add 多一个blob文件,repository的一个文件,内容为文件内容
git add 再多一个blob文件
git commit后 会有两个tree 一个commit
tree,存储blob对象和子tree对象,这类型的对象在Git里面代表的就是一个文件夹,而这个对象的内容就是面向它所包含的文件夹和文件的指针。
commit对象,包含了一个面向根目录tree对象的指针,而且还包含了committer的个人信息还有commit的注释。

三个对象之间关系。总结就是
commit 指向 tree 指向 tree 或者 blob

3、对象实例演示

 

查看对象内容可以参考官方文档,https://git-scm.com/docs/git-cat-file
git cat-file --batch-check --batch-all-objects
the SHA-1, type, and size of each object is printed on stdout
sha1跟md5类似是一个摘要值,然后就是对象类型,大小
 

#查看git版本
C:\\Users>git --version
git version 2.20.1.windows.1

#创建测试目录
D:\\>mkdir gittest

D:\\>cd gittest

#git 初始化
D:\\gittest>git init
Initialized empty Git repository in D:/gittest/.git/

#创建文件index.txt
D:\\gittest>echo "version 1" > index.txt

# index.txt加入暂存区
D:\\gittest>git add index.txt

# 查看所有对象内容
D:\\gittest> git cat-file --batch-check --batch-all-objects
6c58b76a52188643965f3a6704166e8e0424b7fe blob 13

# 查询sha-1对应的文件内容,该对象对应的内容就是index.txt内容
D:\\gittest>git cat-file -p 6c58b76a52188643965f3a6704166e8e0424b7fe
"version 1"

# 创建文件index2.txt
D:\\gittest>echo "version 2" > index2.txt
# index2.txt加入暂存区
D:\\gittest>git add index2.txt
# 查看所有对象内容
D:\\gittest> git cat-file --batch-check --batch-all-objects
6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13

# 查询sha-1对应的文件内容,该对象对应的内容就是index2.txt内容
D:\\gittest>git cat-file -p 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71
"version 2"

#创建新文件夹
D:\\gittest>mkdir dir

#创建新文件夹中的新文件
D:\\gittest>echo "version 1, inside" > ./dir/inside.txt
 
# inside.txt加入暂存区
D:\\gittest>git add ./dir/inside.txt

# 查看所有对象内容
D:\\gittest> git cat-file --batch-check --batch-all-objects
6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13
bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21

# 查询sha-1对应的文件内容,该对象对应的内容就是inside.txt内容
D:\\gittest>git cat-file -p bf97e71de76bcff2bd8aba44710aa5e665eacb99
"version 1, inside"

#提交到本地仓库
D:\\gittest>git commit


D:\\gittest> git cat-file --batch-check --batch-all-objects
39bdea2300491cc90f47551887bfe9503cd4a9d9 tree 38
6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13
bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21
d5c2b878425995af5ddc5202f7058a1ff372b3f3 tree 105



D:\\gittest>git commit
[master (root-commit) 629a4cf] commit 1
 3 files changed, 3 insertions(+)
 create mode 100644 dir/inside.txt
 create mode 100644 index.txt
 create mode 100644 index2.txt

# 查看所有对象内容,commit之后多了两个tree和一个commit
D:\\gittest> git cat-file --batch-check --batch-all-objects
39bdea2300491cc90f47551887bfe9503cd4a9d9 tree 38
629a4cf0fdb33390ad5774b10244512e3d400407 commit 169
6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13
bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21
d5c2b878425995af5ddc5202f7058a1ff372b3f3 tree 105

#查看一个commit
D:\\gittest>git cat-file -p 629a4cf0fdb33390ad5774b10244512e3d400407
tree d5c2b878425995af5ddc5202f7058a1ff372b3f3
author  iaiti<xx@qq.com> 1617247696 +0800
committer  iaiti<xx@qq.com> 1617247696 +0800

# 查看其中一个tree
D:\\gittest>git cat-file -p d5c2b878425995af5ddc5202f7058a1ff372b3f3
040000 tree 39bdea2300491cc90f47551887bfe9503cd4a9d9    dir
100644 blob 6c58b76a52188643965f3a6704166e8e0424b7fe    index.txt
100644 blob 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71    index2.txt


# 更改文件内容
D:\\gittest>echo "version 2" > index.txt

D:\\gittest>git add index.txt

D:\\gittest>echo "version 1 new" > index.txt

D:\\gittest>git add index.txt

D:\\gittest> git cat-file --batch-check --batch-all-objects
0b596a83945ca790976a10bbf005262f1cefe4cc blob 17   		(version 1 new)
39bdea2300491cc90f47551887bfe9503cd4a9d9 tree 38   		(inside.txt)
629a4cf0fdb33390ad5774b10244512e3d400407 commit 169 	(commit)
6c58b76a52188643965f3a6704166e8e0424b7fe blob 13   		(version 1)
8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13   		(version 2)
bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21   		(version 1, inside)
d5c2b878425995af5ddc5202f7058a1ff372b3f3 tree 105  		(dir index.txt  index2.txt)

D:\\gittest>git cat-file -p 0b596a83945ca790976a10bbf005262f1cefe4cc
"version 1 new"


#提交第二次
D:\\gittest>git cat-file -p beaeb2b94a88d6cf03c096f667859239065d1ba8
tree 4fca214cabbc6f8c6a7243f9ea780b66ee895993
parent 629a4cf0fdb33390ad5774b10244512e3d400407
author iaiti <xx@git.com> 1617247963 +0800 
committer iaiti <git@xx.com> 1617247963 +0800

Commit 2

多次更改和提交两次后,所有对象的对应关系

 

4、branch和tag

branch 其实就是一个指向某个commit的指针文件,一般被存放在./.git/refs/heads里面,所以branch只是跨commit而已,按照上图所指示出来的,指向的其实就是master分支
head指向最新commit
tag相当于是静态的 branch ,被存储在./.git/refs/tags里面的文件中。它并不跟随HEAD移动。通常用于标记一个特定的commit,例如某个版本的代码,以方便checkout。

 

5、reset和reverse区别

reset是记录重设,有三种模式

git reset 17cf9ea15f6c63ec04f232c5cd72e0c1b3f657fd
--hard  commit记录重设,但是如果远程仓库已经commit,可以使用git push --force
--mixed commit记录重设,工作区文件修改,暂存区的记录会重置,相当于没到git add阶段,相当于撤销add
--soft   commit记录重设,工作区文件修改和暂存区的记录都会保存

三种模式总结来说就是,相当于做了版本回退,并控制文件是否回退到暂存区前

 

而reverse,也是回退,但是不是重置commit,而是多出一条commit ,提醒其他的开发者或者公司同事,这里有恢复操作。可以
和reset对比结合看。

 

问题来了,reverse还有commit,reset的话中间的commit就不见了, 我要回滚怎么操作?

git reflog记录操作,回滚回之前重置的commit记录。

 

D:\\gittest>git ls-files --stage
100644 bf97e71de76bcff2bd8aba44710aa5e665eacb99 0       dir/inside.txt
100644 0b596a83945ca790976a10bbf005262f1cefe4cc 0       index.txt
100644 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 0       index2.txt
D:\\gittest>
D:\\gittest>echo "version test index" > index.txt
D:\\gittest>
D:\\gittest>git ls-files --stage
100644 bf97e71de76bcff2bd8aba44710aa5e665eacb99 0       dir/inside.txt
100644 0b596a83945ca790976a10bbf005262f1cefe4cc 0       index.txt
100644 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 0       index2.txt

D:\\gittest>git add index.txt

D:\\gittest>git ls-files --stage
100644 bf97e71de76bcff2bd8aba44710aa5e665eacb99 0       dir/inside.txt
100644 be06e3be42f6a2955d61750c86646b7869177f47 0       index.txt
100644 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 0       index2.txt
D:\\gittest>


D:\\gittest>echo "version test index" > index.txt

D:\\gittest>git add index.txt

git commit -m comit3

D:\\gittest>git log
commit b3a0d90be0da1862b4c82fb6beafffaf4113148e (HEAD -> master)
Author: <E8><94><A1><E5><9D><A4><E6><89><BF> <xx.com>
Date:   Thu Apr 29 19:51:51 2021 +0800

    Revert "comit3"

    This reverts commit 6fccca25df481aa1d53ad60075bb37d5e87d8593.

commit 6fccca25df481aa1d53ad60075bb37d5e87d8593
Author: <E8><94><A1><E5><9D><A4><E6><89><BF> <xx.com>
Date:   Thu Apr 29 19:51:21 2021 +0800

    comit3

6、rebase作用

变基,https://git-scm.com/docs/git-rebase 可以查看相关指令信息,

git rebase -i  [startpoint]  [endpoint] 给用户交互界面进行操作

挑选变基的commit

git rebase -i 674c40b

 

 

 

 

 

然后移除多余的commit信息,s的话是合并前面的提交

 

 

从这里可以看到,变基可以合并我前面提交无用的记录。让整个提交的历史更加的简洁,之前有网友举例,vue作者尤雨溪就有这样的处理。

rebase分支不要使用在公共分支上。

 

7、rebase再探究竟,rebase和merge区别

除了合并提交信息,让其更简洁外,是不是还有其他作用,都是合并,那和merge区别是什么,需要这样思考。

假如我有一条功能分支比较久没同步线上代码,或者主分支其实多人合作合并频繁的时候,按照平时的操作都是拉一条分支,然后将master merge到自己分支

结果是这样的


而变基能让自己的一条分支形成直线,不受其他的干扰。

 

总结来说,merge是当前开发分支领先于要合并的分支,那就merge过去,比如开发功能和测试完毕想合并到线上,就是用merge。

如果当前分支许久没拉下来,落后master的,就用rebase,就只把当前的内容合并到自己分支上,而不用理会是什么分支合并过来的。master主分支才需要查看谁合了什么上去。

以上是关于计算机基础——Git的底层原理,reverse和reset的区别,rebase作用的主要内容,如果未能解决你的问题,请参考以下文章

计算机基础——Git的底层原理,reverse和reset的区别,rebase作用

Git系列之底层原理篇

git的核心命令使用和底层原理解析

git基础教程 了解git内部原理(下)

一文讲透 Git 底层数据结构和原理

深度学习计算机底层原理,深度剖析存储器