git学习

git的简单操作大家都理解,但是懂又是另一回事

一、git的熟悉程度小调查

1、了解git object ,如blob、tree、commit等的区别?

概念:Git对象一共有三种:数据对象、树对象以及提交对象,这些对象都被保存在了.git/objects目录下 。

数据对象(blob)

数据对象的产生是在使用git add命令将文件或者目录加入到暂存区时产生的,Git会把一个文件中要存储的数据和一个头部信息一起做SHA-1散列运算,将得到的散列值作为这个文件的路径,

树对象(tree)

接下来我们探讨Git中的树对象, 它能解决文件名保存问题,也允许我们将多个文件组织到一起, Git以一种类似于UNIX系统的方式存储内容,但做了些许简化。所有内容均已树对象和数据对象的形式存储,其中树对象对应了UNIX中的目录项,数据对象大致对应了文件内容。

提交对象(commit)

提交对象中包含一个树对象条目,代表着当前项目快照,从这树对象开始我们就能找到所有所有提交的数据对象,从而形成Git中的一个版本 其他之外还有一些作者/提交者的信息,留空一行,最后是提交注释。

2、知道git reset --soft、git reset、git reset --hard的区别?

当要回退到某一次提交的状态时,可以使用git reset命令。有三个常用参数:--soft,--mixed,--hard。

有三个常用参数:--soft,--mixed,--hard。按照Git文档的习惯,可以写作 git reset [--soft | --mixed | --hard] [<commit>]

其中,<commit>是指commit的hashcode。

也可以使用HEAD代替<commit>,命令为 git reset [--soft | --mixed | --hard] [HEAD]

1.git reset --hard

这个命令 非常危险 ,是 git 中少有的几个会丢失信息的操作。它会把回退点之前的所有信息都删掉,一个不留,干干净净。

举个例子: 现在我把 A 文件修改了两次,到了 C 状态 ,并且已提交。 那么我的分支指针是指向 C , 当前文件编辑的状态也是在 C

   (F)
A-B-C
    ↑
  master
我输入了git reset --hard,结果会变成:
​
 (F)
A-B
  ↑
master

对的, C 状态彻底没有,再也找不回来。

该指令特点是丢失信息,强制删除,把回退点之前的信息都删除
2.git reset --soft

同样是这个状态。

同样是这个状态:

   (F)
A-B-C
    ↑
  master

我输入了git reset --soft,结果是:

 (F)
A-B-C
  ↑
master

文件状态与分支的指针都指向上一个提交,C 还是在的,只是没显示。

该指令特点是分支指针和状态指针一起移动。
3.git reset --mixed

还是这个场景:

   (F)
A-B-C
    ↑
  master

我输入了 git reset --mixed,结果是:

   (F)
A-B-C
  ↑
master

分支指针指向上次提交点,但是文件状态还是在当前文件 C ,我看到的现象就是 C 文件还在,但是没有 add ,是红色的。

该指令特点是分支指针动,而文件状态指针不动

3、听说过git reflog?

git reflog 是一个非常有用的命令,可以展示已经执行过的所有动作的日志。包括合并、重置、还原,基本上包含我们对的我们的分支所做的任何修改。

动图封面

如果我们犯了错,可以根据 reflog 提供的信息通过重置 HEAD 来轻松地重做!

假设我们实际上并不需要合并原有分支。当我们执行 git reflog 命令时,我们可以看到这个 repo 的状态在合并前位于 HEAD@{1}。那我们就执行一次 git reset,将 HEAD 重新指向在 HEAD@{1} 的位置。

动图封面

Reflog操作+回退操作

二、git工作流程

执行git add后

使用cat命令打开

乱码原因是git对储存内容进行了二进制压缩,采用更有效的命令

成功读取数据,blob包含一个文件中要存储的数据和一个头部信息一起做SHA-1散列运算

乱码可以理解成数据的标识数据

上面的58c9bd等信息代表的键是位置,111是存储的数据

在之前的命令中objects新增了两个文件

然后我们发现这个objects是一个tree

tree是一个目录结构,从左往右分是文件权限 、文件类型、文件的内容对应的sha1值、文件名字

增加对应的两个文件

tree流程用图形看

同时我们还多出来一个objects,commit,存储的是快照,提交内容从左到右是,作者名、提交时间、最后一次提交的作者名和提交时间

commit流程从图形上看是这样的

分支

head、分支、普通的tag可以理解成为一个指针,指向对于conmmit的sha1值,从图形上看

问题1:为什么要把文件的权限和文件名储存在tree object里面而不是blob object呢?

  想象一下修改一个文件的命名。如果将文件名保存在blob里面,那么Git只能多复制一份原始内容形成一个新的blob object。而Git的实现方法只需要创建一个新的tree object将对应的文件名更改成新的即可,原本的blob object可以复用,节约了空间。

  问题2:每次commit,Git储存的是全新的文件快照还是储存文件的变更部分?

  由上面的例子我们可以看到,Git储存的是全新的文件快照,而不是文件的变更记录。也就是说,就算你只是在文件中添加一行,Git也会新建一个全新的blob object。那这样子是不是很浪费空间呢?

  这其实是Git在空间和时间上的一个取舍,思考一下你要checkout一个commit,或对比两个commit之间的差异。如果Git储存的是问卷的变更部分,那么为了拿到一个commit的内容,Git都只能从第一个commit开始,然后一直计算变更,直到目标commit,这会花费很长时间。而相反,Git采用的储存全新文件快照的方法能使这个操作变得很快,直接从快照里面拿取内容就行了。

  当然,在涉及网络传输或者Git仓库真的体积很大的时候,Git会有垃圾回收机制gc,不仅会清除无用的object,还会把已有的相似object打包压缩。

  问题3:Git怎么保证历史记录不可篡改?

  通过SHA1哈希算法和哈希树来保证。假设你偷偷修改了历史变更记录上一个文件的内容,那么这个问卷的blob object的SHA1哈希值就变了,与之相关的tree object的SHA1也需要改变,commit的SHA1也要变,这个commit之后的所有commit SHA1值也要跟着改变。又由于Git是分布式系统,即所有人都有一份完整历史的Git仓库,所以所有人都能很轻松的发现存在问题。

大佬参考

B站视频链接: [中文] 这才是真正的 Git——Git 内部原理揭秘!(freeCodeConf 2019 深圳站)_哔哩哔哩_bilibili PPT 链接: 这才是真正的Git——Git原理及实用技巧

本人参考文章:

1、Git对象(objects)简介_.git/objects-CSDN博客

2、git reset 命令详解 - 简书

3、关于 git reset 命令几个常用参数的理解_git reset的各种参数意义-CSDN博客

4、Git工作流常用命令 - 知乎

5、Git内部原理揭秘!从文件更改到代码储存,Git究竟是怎么实现的_网易订阅

6、这才是真正的Git——Git实用技巧 - LZANE | 李泽帆(靓仔)

  • 35
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值