【Git教程】(四)版本库 —— 存储系统,存储目录,提交对象及其命名、移动与复制~

news2024/9/24 17:37:00

Git教程 · 版本库

  • 1️⃣ 一种简单而高效的存储系统
  • 2️⃣ 存储目录:Blob 与 Tree
  • 3️⃣ 相同数据只存储一次
  • 4️⃣ 压缩相似内容
  • 5️⃣ 不同文件的散列值相同
  • 6️⃣ 提交对象
  • 7️⃣ 提交历史中的对象重用
  • 8️⃣ 重命名、移动与复制
  • 🌾 总结

事实上,我们即使不了解版本库的具体工作方式,也一样可以将 Git 用得风生水起。但 如果我们了解了 Git 存储和组织数据的方式,就能对工作流有一个更好的理解。当然,如果你真的很讨厌谈理论,也可以选择跳过本章的正文,只选择性地读一下部分内容即可。

Git 主要由两个层面构成。其顶层结构就是我们所用的命令,例如 logresetcommit 等。这些命令使用起来很方便,并提供了许多可调用的选项。Git 的开发者们称它们令为瓷质命令 (porcelain command)。
而对于其底层结构,我们则称之为管道 (plumbing) 。 这里主要是一组带有少量选项的简 单命令,瓷质命令就是以此为基础被构建出来的。管道命令很少被直接用到。本章将为你提供一些了解该系统管道层结构的机会。

在这里插入图片描述


1️⃣ 一种简单而高效的存储系统

Git 的核心是一个对象数据库。该数据库可用来存储文本或二进制数据,例如对于某文件 的内容。我们可通过带 -w 选项 (w 代表写入)的 hash-object 命令将其作为一条记录插入到该对象数据库中。

> git hash-object -w hello.txt
28cf67640e502fe8e879a863bdlbbcd4366689e8

每当我们存储了这样一个对象, Git 就会返回一个40个字符的代码,这是被存储对象的 键值。请记住它,我们日后需要用该键值配合带 -p 选项 (p代表打印)的cat-file 命令来访问这个对象。

> git cat-file -p 28cf67640e
Hello World!

对象数据库是一个非常高效的实现。即使对于一个有着非常长提交历史的大型项目(例如Linux内核,这是一个拥有 200000次提交和近两百万个对象的项目)来说,访问其版本库 中对象的操作也几乎可在瞬间完成。Git 非常适合用于那些拥有大量小型源文件的项目。其性能瓶颈只有在总数据量非常巨大的时候才能显现出来。对于那些想要管理大量二进制文件的人来说,Git 版本库显然是不二的选择。


2️⃣ 存储目录:Blob 与 Tree

在文件和目录的存储上,Git 使用了一种包含两种节点类型的简单树结构。其文件内容将 保持不变,并以blob 对象的形式按字节被存储对象数据库中。而目录则将用tree 对象来表示, 它们看起来应该像如图所示。

在这里插入图片描述

> git cat-file -p 2790ef78
100644 blob 507d3a30ae9ed53bcf953744c5f5c9391a263356 README
040000 tree 91c7822ab43800b0e3c13049519587df4fd74591 src

正如你将如上看到的, tree 对象中包含了文件和子目录。其中的每个条目都被分配了 相应的访问权限(例如上面的100644)、类型(即 blob 还是 tree), 以及由该文件内容、该文
件或目录名称生成的散列值。


3️⃣ 相同数据只存储一次

为了节省内存空间, Git 对于相同数据将只存储 一 次。例如在下面这个例子中,foo.txtcopy-of-foo.txt 将返回相同的散列值,因为它们的文件内容是相同的。

> git hash-object -w foo.txt
a42a0aba404c21le8fdf33d4edde67bb474368a7
> git hash-object -w copy-of-foo.txt
a42a0aba404c21le8fdf33d4edde67bb474368a7

通过这种方法, Git 不仅能够节省内存,同时也能在性能上得到提升。许多Git 操作之所以快,就是因为它们的算法只比较相关的散列值,而不需要查看其实际数据。


4️⃣ 压缩相似内容

Git 不仅可以对相同的文件内容进行合并,每当程序员们所创建的新文件在内容上与前人 只有区区几行的区别时,Git 可以采用增量方法来存储这些文件,在这种情况下,包文件中将只存储原始版本后来被改变的那一部分。

要想做到这一点,我们就要在想节省空间时使用 gc 命令。这样一来,Git 就会删除所有多余的、不再接受任何分支头访问的提交,并将剩下的提交存储到包文件中。对于那些源代码占绝大多数的项目来说,这就等于实现了某种令人惊叹的高压缩处理。通常情况下,当前版本未压缩的工作区内容大小往往要比包含多年项目历史并打包的Git 版本库还要大得多。


5️⃣ 不同文件的散列值相同

当不同文件的散列值相同时,情况会很糟糕,因为 Git 是通过散列值来识别内容的。因此, 一 旦内容各不相同的文件出现散列值相同的情况,Git 就无法提供正确的数据了,我们称这种情况为敬列冲突(hash collision)。

好消息是,敬列冲突是一种非常罕见的事件。其原因在于,散列值的可能取值至少有2160 种。而即使是Linux 内核项目在运作5年之后,版本库中也就“仅有”大约221个对象。

当然从理论上而言,SHA1 敬列算法是有缺陷的,你可以在 SHA1 算法中找到251 中会 引起敬列冲突的操作。然而,格拉茨科技大学 (Graz University of Technology) 的一个研究项目曾从2007年尝试到2009年,目的是想找出一个(!) 这样的散列冲突,结果以失败告终。

总而言之,在当今版本控制所在的环境下,我们可以认为它是安全的。

6️⃣ 提交对象

我们所做的历次提交也被存储在对象数据库中,它们的格式很简单。

> git cat-file -p 64b98df0
tree 319c67d41a0b3f7464550b41db4bb1584939ad2a
parent 6c7f1ba0828a5b595026e08d2476808105a6b815
author Bjorn Stachmann <bs@test123.de>1295906997  +0100
committer Bjorn Stachmann <bs@test123.de>1295906997  +0100
Section on trees & blobs.

除了作者、提交者、日期以及注释这些元数据外,每个提交对象还在对象数据库中放入 了一些其他对象的散列值。例如: tree 对象负责描述该提交的内容。它还包含了该项目的根目录信息,并且与上文提到的一样,它也将以tree 和 blob 对象的方式呈现。而 parent 对象则指的是它的上一次提交。


7️⃣ 提交历史中的对象重用

除了最初的那次提交外,版本库中的每个提交对象上面都至少会存在一个前提交对象(即 父对象)。通常来说, 一次提交往往只涉及项目中少数文件的修改,其他大部分文件和目录不会发生变化。所以,我们会希望 Git 尽可能多地重用前次提交中的相关对象。

下面我们来看一个具体的例子(见下图)。某一提交(即自顶向下第二排中第二个被 实线箭头所指向的那个标题为 “commit” 的方框)中包含了一个README 文件,以及一个 用于包含其他文件的 src 目录。然后,如果在新建的提交(即图中第一行用虚线箭头所指向 的那个标题为 “commit” 的方框)中,被修改的只有 README 文件, Git 就会专门为该 README 文件创建一个新的blob对象。而对于src 目录,则继续沿用现有的tree对象与相应的 blob 对象。

在这里插入图片描述


8️⃣ 重命名、移动与复制

在许多版本控制系统中,我们都可以对文件的重命名及其修改时间的历史进行跟踪监视。
它们大多数通常是通过某个特定的文件移动或重命名命令来实现的。例如在 Subversion 中,我们可以用 svn move 来移动文件。但是如果用户想要将文件在图形界面中拖放到某一新的位置的话, Subversion 就无能为力了。对于这种情况, Subversion 不会认为这是个移动操作,而会将其记录为先删除,再另行新建该文件的操作过程。

对此,Git 采用了不同的方法:它没有选择去存储与文件移动操作相关的信息,而是采用 了重命名检测算法。在该算法中,如果一个文件在某一次提交中消失了,它依然会存在于其 前次提交中。而如果某个拥有相同名字或相似内容的文件出现在了另一个位置, Git 就会自动检测到。如果是这种情况, Git 就会假定该文件被移动过了。下面我们以下图中的情况为例 来演示一下。你可以看到:第二次提交中已经没有了 foo.txt 文件,它可能被移动了。随后,Git 又自动检测到新增文件中有一个与之内容相似的文件,位于src/foo-moved.txt, 这一过程就成为了重命名操作。

在这里插入图片描述Git 会自行显示出被重命名或移动的文件。

  1. 先获取一份摘要
    我们可以用 log 命令的-M 选项 ( 即“move”) 来激活重命名的检测算法。如果想要格式化输出的信息,我们可以对其使用–summary 选项来显示文件修改的相关信息。但这段输 出很长也是个问题。如果我们想要简短一些,也可以用grep命令来对输出进行筛选。另外,百分比显示了源文件和目标文件的相似度。

    > git log --summary -M90% | grep -e "^ rename"
    rename foo.txt => foo-renamed.txt(90%)
    rename src/{before =>after}/bar.txt(100%)
    
  2. 跟踪被移动文件的历史
    我们可以用 log 命令的–follow 选项来连续取出文件被重命名之后的历史记录(当然,该做法仅适用于单文件操作)。如果不使用该选项,日志就会在该文件被重命名的那一刻停止。

    > git log --follow  foo-renamed.txt
    

我们还可以透过-C 选项来跟踪被复制的数据。

> git log --summary -C90% | grep -e "^copy"

如果有必要的话,我们也可以用 --find-copies-harder选项来使Git 做一个更长的计算操作。只要该选项被激活,Git 就会去检查相关提交中的所有文件,并不仅仅是那些已更改的文件。

我们也可以将重命名检测配制成 Git 的默认选项。这样一来,我们就无需在每次使用 log
命令时为其指定-M--follow 选项了。

> git config diff.renames true

我们可以按照以下步骤找出谁最后修改了那几行代码,以及修改的时间。

  1. 逐行打印源头信息
    当我们将某些较大的代码块复制或移动到其他文件中时,Git 甚至可以确定其中某几行 代码的来源。而且, blame 命令还可以显示出最后一次修改这几行代码的人及其修改时间。

    > git blame -M -C -C -C copied-together.txt 
    f5fdbad0 foo.txt (Rene  2010-11-1418:30:42  +0100  1)One
    a5b80903 bar.txt (Bjorn  2011-01-3121:32:49 +0100  2)Two or
    f5fdbad0 foo.txt (Rene  2010-11-1418:30:42  +0100  3)Three
    

其中的 -M 选项(M 代表“move”) 暗示的是文件的复制和移动操作。 -C 选项也可用于 检测相同提交中的文件副本。但我们还可以用多个-C 选项来搜索该文件在更多提交中的副本。对于大型的版本库来说,这种操作有时候会需要较长的时间。

🌾 总结

  • 对象数据库:所有提交中的文件、目录以及相关的元数据都将被存储在该数据库中。
  • SHA1 散列值:我们可以通过一个SHA1 散列值从对象数据库中捡取相关对象。SHA1 散列值是一种针对文件内容的加密校验值。
  • 相同数据只存储一次:内容相同的对象拥有相同的 SHA1 散列值,并且只存储一次。
  • 相似的数据会被压缩:对于内容相似的数据, Git 会针对其被修改的部分采取增量存储的方法。
  • Blob对象:文件的内容将会被存储在相应的blob对象中。
  • Tree 对象:目录会被存储在相应的 tree对象中。 一个 tree 对象中通常会包含一份文件 名列表,包含这些文件名和储存在blob 或 tree 对象中内容的 SHA1 散列值。
  • 提交图:我们的提交对象会沿着各自的 tree 和 blob对象,形成一个提交图。
  • 重命名检测:文件的重命名和移动操作在提交之前无需报备。Git 可以自动根据文件 内容的相似度来识别操作。例如:git log-follow 命令。
  • 庐山真面目:我们可以通过blame 命令来确定某几行代码的来源,即使这些代码们已 被移动或复制到了别处。


温习回顾上一篇(点击跳转)
《【Git教程】(三)提交详解 —— add、commit、status、stach命令的说明,提交散列值与历史,多次提交及忽略 ~》

继续阅读下一篇(点击跳转)
《【Git教程】(五)分支 —— 并行式开发,分支相关操作(创建、切换、删除)~》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1483463.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

带你玩转java封装和继承(上)

上次带大家学习了java里面比较重要的知识点类和对象&#xff0c;而且我们知道java是一门面向对象的语言&#xff0c;有时一个程序里可能有很多类&#xff0c;那么这么多类他们之间有什么联系吗&#xff1f;今天就带大家学习一下java类之间的关系。 什么是继承&#xff1a; 我们…

摄像机LookDirection参数对模型缩放灵敏度的影响

继续整上回的wpf 3d obj模型程序&#xff1b; 它用HelixToolKit加载了以后&#xff0c;默认可以用鼠标操作模型&#xff0c;中键缩放模型&#xff1b; 有的时候中键稍微滚动几下模型就不见了&#xff1b; 用不同的模型试了一下&#xff1b;中键缩放的灵敏度&#xff0c;就是…

FreeRTOS学习笔记-基于STM32(1)基础知识

一、裸机与RTOS 我们使用的32板子是裸机&#xff0c;又称前后台系统。裸机有如下缺点&#xff1a; 1、实时性差。只能一步一步执行任务&#xff0c;比如在一个while循环中&#xff0c;要想执行上一个任务&#xff0c;就必须把下面的任务执行完&#xff0c;循环一遍后才能执行…

BUGKU bp

打开环境&#xff0c;他提示了弱密码top1000&#xff0c;随便输入密码123抓包爆破 发现长度都一样&#xff0c;看一下响应发现一段js代码&#xff0c;若r值为{code: bugku10000}&#xff0c;则会返回错误&#xff0c;通过这一句“window.location.href success.php?coder.cod…

StarRocks——Stream Load 事务接口实现原理

目录 前言 一、StarRocks 数据导入 二、StarRocks 事务写入原理 三、InLong 实时写入StarRocks原理 3.1 InLong概述 3.2 基本原理 3.3 详细流程 3.3.1 任务写入数据 3.3.2 任务保存检查点 3.3.3 任务如何确认保存点成功 3.3.4 任务如何初始化 3.4 Exactly Once 保证…

【MATLAB】 ICEEMDAN信号分解+FFT傅里叶频谱变换组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 展示出图效果 1 ICEEMDAN信号分解算法 ICEEMDAN 分解又叫改进的自适应噪声完备集合经验模态分解&#xff0c;英文全称为 Improved Complete Ensemble Empirical Mode Decomposition with Adaptive Noise。 ICEEMDAN (I…

【书生·浦语大模型实战营】第 2 节 -课后作业

第二节 -轻松玩转书生浦语大模型趣味 Demo-课后作业 0.课程体验0.1 鸡兔同笼0.2 逻辑推理0.3 AI会毁灭人类吗&#xff1f; 1.课后作业1.1 基础作业1.1.1 作业11.1.2 作业2 0.课程体验 课程链接&#xff1a;https://github.com/internLM/tutorial 首先&#xff0c;这个课程是免费…

《Spring Security 简易速速上手小册》第7章 REST API 与微服务安全(2024 最新版)

文章目录 7.1 保护 REST API7.1.1 基础知识详解7.1.2 重点案例&#xff1a;使用 JWT 进行身份验证和授权案例 Demo 7.1.3 拓展案例 1&#xff1a;API 密钥认证案例 Demo测试API密钥认证 7.1.4 拓展案例 2&#xff1a;使用 OAuth2 保护 API案例 Demo测试 OAuth2 保护的 API 7.2 …

vue 之 Quill编辑器封装

安装 npm install vue-quill-editor --save <template><div><el-upload:action"uploadUrl":before-upload"handleBeforeUpload":on-success"handleUploadSuccess":on-error"handleUploadError"name"file":sh…

家政行业的数字转型:开发智能化家政预约APP的挑战与机遇

为了适应这一变化&#xff0c;许多家政企业开始积极探索数字化转型&#xff0c;其中包括开发智能化预约APP。本文将探讨开发智能化预约APP所面临的挑战与机遇。 ​一、挑战&#xff1a; 1.用户体验设计&#xff1a; -开发智能化预约APP需要注重用户体验设计&#xff0c;包括…

Pytest插件pytest-selenium-让自动化测试更简洁

在现代Web应用的开发中&#xff0c;自动化测试成为确保网站质量的重要手段之一。而Pytest插件 pytest-selenium 则为开发者提供了简单而强大的工具&#xff0c;以便于使用Python进行Web应用的自动化测试。本文将深入介绍 pytest-selenium 插件的基本用法和实际案例&#xff0c;…

Web Tomcat

目录 1 前言2 Tomcat的安装3 Tomcat文件的构成4 Tomcat的使用步骤 1 前言 Tomcat是一个 http(web)的容器&#xff0c;笼统的理解一下所有的网站都叫做web。这个web容器可以把我们的前端(htmlcssjs)和后端(servlet)代码都运行起来。 Tomcat是一个免费的开源的Servlet容器&#…

可视化场景(1):销售业绩大屏-是骡子是马,牵出溜溜

销售业绩可视化大屏的是一种有力的销售数据管理工具&#xff0c;贝格前端工场分享一批给友友们&#xff0c;如需要定制&#xff0c;可以与我们联络&#xff0c;开始了。 销售业绩可视化大屏是一种将销售数据以图表、数字、文字等形式展示在大屏幕上的数据可视化工具。它的作用主…

如何在OnlyFans付费订阅?

OnlyFans成立于2016年&#xff0c;允许内容创作者从用户那里获得资金&#xff0c;用户需要支付订阅费用才能查看他们的内容。它在多个领域受到欢迎&#xff0c;包括音乐、健身、摄影&#xff0c;以及某种内容创作。 如何在OnlyFans付费订阅&#xff1f; 我们订阅之前需要一张…

JOSEF约瑟 漏电继电器LLJ-400F 配套零序互感器φ100mm 50-500mA 0.1S 导轨安装

系列型号&#xff1a; LLJ-150F(S)漏电继电器 LLJ-160F(S)漏电继电器 LLJ-200F(S)漏电继电器 LLJ-250F(S)漏电继电器 LLJ-300F(S)漏电继电器 LLJ-320F(S)漏电继电器 LLJ-400F(S)漏电继电器 LLJ-500F(S)漏电继电器 LLJ-600F(S)漏电继电器 一、产品用途及特点 LLJ-FS系列漏电继电…

图表背后的智慧:办公场景中的数据可视化革新

在现代办公场景中&#xff0c;数据可视化的应用已经成为提高效率、推动创新的得力工具。无论是管理层还是普通员工&#xff0c;都能从数据可视化中受益匪浅。下面我就以可视化从业者的角度&#xff0c;简单聊聊这个话题。 首先&#xff0c;数据可视化提升了数据的易读性与理解性…

GitLab代码服务器搭建

在Ubuntu上搭建GitLab服务器需要按照一系列步骤进行操作。以下是一个基本的指南&#xff1a; 安装必要的依赖包&#xff1a;首先&#xff0c;确保系统已经安装了所需的依赖包。这通常包括curl、openssh-server、ca-certificates和postfix&#xff08;如果你打算使用GitLab的邮件…

985机械研一转码,java还是c++?

985机械研一转码&#xff0c;java还是c&#xff1f; 在开始前我分享下我的经历&#xff0c;我刚入行时遇到一个好公司和师父&#xff0c;给了我机会&#xff0c;一年时间从3k薪资涨到18k的&#xff0c; 我师父给了一些 电气工程师学习方法和资料&#xff0c;让我不断提升自己&…

初学Vue总结

0 Vue概述 问题&#xff1a;我们已经学过了htmlCssjavascript,可以开发前端页面了&#xff0c;但会发现&#xff0c;效率太低了。那么&#xff0c;有没有什么工具可以提高我们的开发效率&#xff0c;加快开发速度呢&#xff1f; 他来了&#xff0c;他来了&#xff0c;他大佬似…

总结一下linux性能检测和调优手段

1.perf 是 Linux 系统中性能分析工具&#xff0c;用于收集性能相关的信息。它可以用于查看 CPU 使用情况、内存性能、磁盘 I/O 等&#xff0c;以帮助开发者找到性能瓶颈。 以下是一些 perf 常见用法和示例&#xff1a; 1. CPU Profiling a. 查看 CPU 使用率 perf stat -e cpu…