CS61B Spring 2021 proj2 gitlet

Gitlet

  • 项目简介
  • 整体结构
    • 对象概念(object concept)
    • 追踪文件(track file)
    • 分支管理(branch management)
    • 持久化目录结构(folder structure)
  • 命令功能与具体实现
    • init
    • add
    • commit
    • rm
    • log
    • global-log
    • find
    • status
    • checkout
    • branch
    • rm-branch
    • reset
    • merge
    • add-remote
    • rm-remote
    • push
    • fetch
    • pull
  • 总结
  • github地址

项目简介

gitlet是一个版本控制系统,与git类似,但对git的一些功能做了一些简化,可以看作是低配版的git,支持大多数git支持的功能,比如add/commit等等。在本项目中,系统维护的文件仅考虑当前工作目录下(CWD, current working directory)的子文件,即不包括子文件夹。
该系统支持的功能主要有:

  • 提交commit用于维护历史版本,即commit功能
  • 将某个历史commit(也可以是某个branch的head)的某个文件(或整个commit’s tracked file set)提取到当前工作目录下,即checkout功能
  • 查看历史上的commit信息,即log功能
  • 维护多个不同的commit分支,即branch功能
  • 把两个分支合并,即merge功能

整体结构

对象概念(object concept)

在gitlet中,两个重要的对象为:
commits: 由timestamp, log message, tracked files set(mapping from filename to blob reference), first parent commit reference, second parent commit reference(for merge)组成
blobs: 由文件名和文件内容组成,由于同一个文件可能有不同的版本,故文件名相同的blobs也可能是不同的对象(内容不同)
每一个对象(commit或blob)都有一个唯一的对象ID(称为UID或SHA-1ID),它由SHA-1哈希函数生成,同类型的不同对象出现哈希冲突的概率极小。于是可以使用UID作为blobs或者commits的文件名,以便于序列化与反序列化操作,也称为持久化(persistence)。当然由于blob对象和commit对象的哈希值可能冲突,于是分为两个文件夹存放。当对象实现持久化后,UID也可作为对象的引用(reference),上面commit中包含的许多reference可以理解为对象的UID。

追踪文件(track file)

与git类似,跟踪(track)一个文件首先需要将其添加进缓存区(staging area for addition),然后在进行commit提交缓存区的文件并清空缓存区。缓存区包含两个区域,for addition和for removal,为了一些命令的方便,addition缓存区个人采用Treemap维护文件名到blob reference的映射,removal缓存区使用文件名的set维护即可(在命令实现部分还会细讲)。
缓存区除了维护文件名到blob reference的映射之外,还需要保存一些临时的blob实体(不然哪来的blob reference),这里是个人理解,因为缓存区的文件状态并不稳定,而我们只关注最终commit时候的文件状态。

分支管理(branch management)

多个分支的维护的用途是方便用户管理多个不同版本的项目,比如项目的A版本作为一个分支,B版本作为另外一个分支,分支间可以来回切换。
系统需要维护分支的每一个头部(branch head),分支头部其实就是某个commit的reference(即UID);同时需要维护一个全局的当前分支头部,以支持某些命令的使用。这部分内容也需要持久化。

持久化目录结构(folder structure)

如下图所示,在当前工作目录下系统需要创建一个.gitlet文件夹用于存放持久化文件,包括以下子文件(或文件夹):

  • objects: 保存commits和blobs两种对象文件
  • branches: 保存分支头部文件(如默认的master分支)
  • staging: 保存缓存区文件
  • HEAD: 保存系统当前commit的UID
  • CURRENT_BRANCH: 保存当前所在分支的名字
  • TREE: 保存当前的commit集合(由于在写merge之前都以为commit是树形结构所以取名为TREE,后来懒得改了,其实是DAG结构)
    在这里插入图片描述

命令功能与具体实现

init

命令: java gitlet.Main init
具体功能描述:
在当前工作目录下创建一个用于持久化对象的隐藏目录.gitlet,在该目录下按照上述文件目录结构初始化所有目录与文件。创建一个初始的commit,包含信息initial commit,将头指针HEAD指向该commit。创建一个默认分支master,将该分支的头部也指向该commit。
时间复杂度: O ( 1 ) O(1) O(1)
错误提示:
如果在当前目录下已经存在.gitlet目录,即已经在当前工作目录下初始化过,则提示A Gitlet version-control system already exists in the current diretory.

add

命令: java gitlet.Main add [file name]
具体功能描述:
将给定的工作目录文件添加到暂存区中(staging area),由于我将暂存区分为两部分(addition与removal),于是添加到addition中。
如果当前工作目录中该文件的版本与当前HEAD指针指向的commit中该文件的版本一致,则不需要添加至addition;且如果addition中存在该文件,则移除它。(当文件修改之后执行add,又修改回原始版本之后再执行add,则会产生这个情况)。
如果给定文件存在于removal中,则将其从removal中移除。
时间复杂度:
由于我使用TreeMap维护每个commit的tracked files,于是找到commit中该文件的版本需要O(logN)的复杂度(N是该commit的tracked files数量)。
错误提示:
如果所指定的文件在工作目录中并不存在,则提示File does not exist.并退出程序。

commit

命令: java gitlet.Main commit [message]
具体功能描述:
使用message与当前date新创建一个commit,继承HEAD指向的当前commit的所有文件信息。
根据当前addition与removal中的文件,修改新commit中的tracked files。
修改HEAD指针与BRANCH头指针指向的commit。
清空staging area。
时间复杂度:
继承文件信息的复杂度为NN为HEAD指向commit的tracked files数量);修改tracked files的复杂度为MlogNM为addition与removal中的文件数量总和);故总复杂度为 O ( N + M l o g N ) O(N+MlogN) O(N+MlogN)
错误提示:
如果staging area(addition与removal)中没有文件,则报错No changes added to the commit.;如果所输入信息为空,则报错Please enter a commit message.

rm

命令: java gitlet.Main rm [file name]
具体功能描述:
如果所指定文件存在于addition中,则将其从addition中移除。
如果当前文件在当前的commit的tracked files中,则将其添加进removal中,且如果当前文件存在于工作目录中,则将其删除。
时间复杂度: O ( l o g N ) O(logN) O(logN) N N N为当前commit中文件数量
错误提示:
如果所指定文件不存在于addition中且不存在于当前commit的tracked files中,则报错No reason to remove the file.

log

命令: java gitlet.Main log
具体功能描述:
从HEAD指针指向的commit开始,沿着parent往根走(根就是initial commit),按照一定格式输出commit的信息,忽略second parent(在merge的时候会说到)。
时间复杂度: O ( N ) O(N) O(N) N N N为路径上的commit数量

global-log

命令: java gitlet.Main global-log
具体功能描述: 与log类似,但是需要输出所有commit的信息,不关心输出的前后顺序。
时间复杂度要求: O ( N ) O(N) O(N) N N N为当前系统中所有的commit数量

find

命令: java gitlet.Main find [commit message]
具体功能描述:
根据给出的commit message,输出拥有该信息的所有commit id。
时间复杂度要求: O ( N ) O(N) O(N) N N N为当前系统中所有的commit数量
错误提示:
所有未找到满足条件的commit,则报错Found no commit with that message.

status

命令: java gitlet.Main status
具体功能描述:
按照指定格式输出当前的几个信息,包括BranchesStaged FilesRemoved FilesModifications Not Staged For CommitUntracked Files(均按照字典序升序排序)。
其中,Branches中当前分支前面需要加个*Staged FilesRemoved Files分别表示暂存区中标志添加或删除的文件名(即addition和removal中的文件)。
具体实现起来也不复杂,由于已经持久化了Branch、addition和removal的集合,直接遍历输出即可。
剩下两个信息虽然是extra的,但是比较容易实现就顺便讲一讲。
一个文件是modified but not staged当且仅当它满足一下任意一个条件:

  • 在当前的commit中被追踪(tracked),且在当前的工作目录下被修改但为添加到addition中;
  • 在当前的commit中被追踪(tracked),且在当前工作目录下被删除但未添加到removal中;
  • 已经添加到addition中,但是addition中该文件的内容与当前工作目录下的不同;
  • 已经添加到addition中,但是在当前工作目录下被用户删除。

如果一个文件存在于当前工作目录中,但是既没有被当前的commit所追踪(tracked),又没有被添加到addition中,那么它属于Untracked Files
extra的实现,个人是遍历了工作目录、addition还有当前commit的tracked files中的所有文件,判断是否满足上述条件。

时间复杂度要求: O ( N + M + K ) O(N+M+K) O(N+M+K),其中 N N N为分支数, M M M为当前工作目录下的文件数, K K K为addition和removal中的文件数量。(该复杂度未考虑extra的内容)
错误提示: 无错误

checkout

命令:
1.java gitlet.Main checkout -- [file name]
2.java gitlet.Main checkout [commit id] -- [file name]
3.java gitlet.Main checkout [branch name]
具体功能描述:

时间复杂度要求:
错误提示:

branch

命令: java gitlet.Main status
具体功能描述:
时间复杂度要求:
错误提示:

rm-branch

命令: java gitlet.Main status
具体功能描述:
时间复杂度要求:
错误提示:

reset

命令: java gitlet.Main status
具体功能描述:
时间复杂度要求:
错误提示:

merge

命令: java gitlet.Main status
具体功能描述:
时间复杂度要求:
错误提示:

add-remote

待更

rm-remote

待更

push

待更

fetch

待更

pull

待更

总结

基本熟悉了git的使用方法以及实现原理;其实总体实现起来并不是特别的困难,跟着文档走基本上都没啥太大问题,主要是一开始不知道从何入手,主要是不知如何设计.gitlet文件夹的结构,参考了git的设计之后其实也就解决了这个问题,万事开头难,开始写代码就容易起来了。
这个项目应该是我写代码以来注释写的最多的项目了,因为怕写着写着忘了(虽然说最后注释对我而言也没啥用处),之后其实不用写太多注释。

github地址

CS61B Spring 2021 GitLet

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

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

相关文章

深入探索Python数据容器:绚丽字符串、神奇序列切片与魔幻集合奇遇

一 数据容器:str(字符串) 1.1 字符串初识 字符串也是数据容器的一员,字符串是一种数据容器,用于存储和处理文本数据。字符串是字符的容器,一个字符串可以存放任意数量的字符,可以包含字母、数字、标点符号、空格等字…

微信小程序开发【从0到1~入门篇】2023.08

一个小程序主体部分由三个文件组成,必须放在项目的根目录,如下: 文件必须作用app.js是小程序逻辑app.json是小程序公告配置app.wxss否小程序公告样式表 3. 小程序项目结构 一个小程序页面由四个文件组成,分别是: 文…

Swintransformer模型的优化

SwinTransformer模型优化 文章目录 SwinTransformer模型优化1.SwinTransformer概述2.性能瓶颈分析3.模型优化3.1.transpose消除3.2.更好的layergroup3.1.1.SliceOp3.1.2.SqueezeOp3.1.3.weight切分 4.优化效果 1.SwinTransformer概述 自从Transformer在NLP任务上取得突破性的进…

20天突破英语四级高频词汇——第②天

20天突破英语四级高频词汇~第2天加油(ง •_•)ง💪 🐳博主:命运之光 🌈专栏:英语四级高频词汇速记 🌌博主的其他文章:点击进入博主的主页 目录 20天突破英语四级高…

Bert详细学习及代码实现详解

BERT概述 BERT的全称是Bidirectional Encoder Representation from Transformers,即双向Transformer的Encoder,因为decoder是不能获要预测的信息的。在大型语料库(Wikipedia BookCorpus)上训练一个大型模型(12 层到 …

【基础IO】文件系统 {磁盘的物理结构,存储结构,逻辑结构;CHS 和 LBA 寻址方式;磁盘分区和块组;文件inode;软硬链接}

文件系统 文件分为: 内存文件:被进程打开的文件,文件被加载到内存中供进程快速读写。磁盘文件:没有被打开的文件,保存在磁盘上。磁盘文件被分门别类的存储和管理,用于支持更好的存取。 提示: …

华为发布数字资产继承功能

在华为开发者大会2023(HDC.Together)上,华为常务董事、终端BG CEO、智能汽车解决方案BU CEO余承东正式发布了数字资产继承功能,HarmonyOS提供了安全便捷的数字资产继承路径。 在鸿蒙世界中,我们每个人在每台设备、应用…

复原 IP 地址——力扣93

文章目录 题目描述回溯题目描述 回溯 class Solution{public:static constexpr int seg_count=4<

第6集丨Vue 江湖 —— Class 与 Style 样式绑定

目录 一、class绑定1.1 字符串1.2 数组1.3 对象1.4 完整案例 二、style绑定2.1 案例2.2 效果 操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute&#xff0c;所以我们可以用 v-bind 处理它们&#xff1a;只需要通过表达式计算出字符串结果即可…

Typescript - 索引签名

目录 1&#xff0c;什么是索引签名1&#xff0c;js 中使用对象的属性2&#xff0c;ts 中的索引签名3&#xff0c;扩展索引签名定义的类型 2&#xff0c;与 Record 对比3&#xff0c;遇到的问题1&#xff0c;索引 key 的类型问题&#xff0c;keyof2&#xff0c;索引 key 的类型问…

uni-app:实现表格多选及数据获取

效果&#xff1a; 代码&#xff1a; <template><view><scroll-view scroll-x"true" style"overflow-x: scroll; white-space: nowrap;"><view class"table"><view class"table-tr"><view class&quo…

mysql高级三:sql性能优化+索引优化+慢查询日志

内容介绍 单表索引失效案例 0、思考题&#xff1a;如果把100万数据插入MYSQL &#xff0c;如何提高插入效率 &#xff08;1&#xff09;关闭自动提交&#xff0c;只手动提交一次 &#xff08;2&#xff09;删除除主键索引外其他索引 &#xff08;3&#xff09;拼写mysql可以执…

Typescript中的元组与数组的区别

Typescript中的元组与数组的区别 元组可以应用在经纬度这样明确固定长度和类型的场景下 //元组和数组类似&#xff0c;但是类型注解时会不一样//元组赋值的类型、位置、个数需要和定义的类型、位置、个数完全一致&#xff0c;不然会报错。 // 数组 某个位置的值可以是注解中的…

新能源电车交流充电桩控制主板的安全性维度

你是否想过&#xff0c;交流充电桩主板的安全性有多重要?它不仅关乎充电设备的寿命&#xff0c;还关乎电网的安全。今天我们就来探讨一下&#xff0c;如何从多个维度保证交流充电桩主板的安全性。 首先&#xff0c;交流充电桩主板采用多重安全保护技术&#xff0c;可以有效地保…

SM2算法的抗侧信道攻击

SM2 算法中底层模块抗侧信道 标量乘 ( [ k ] G [k]G [k]G) 运算过程中需要用到大量的倍点运算与点加运算。传统倍点运算与点加运算之间由于需要的运算次数不同&#xff0c;功耗存在明显区别&#xff0c;攻击者可以通过功耗波形特征分析密钥信息。传统算法如下图所示&#xff1a…

11. 使用tomcat中碰到的一些问题

文章目录 问题一&#xff1a;Tomcat的startup.bat启动后出现乱码问题二&#xff1a;一闪而退之端口占用问题三&#xff1a;非端口问题的一闪而退问题四&#xff1a;服务器的乱码和跨域问题问题五: 在tomcat\webapps\下创建文件夹为什么tomcat重启就会丢失问题六&#xff1a;Tom…

【C++】AVL(平衡二叉搜索树)树的原理及实现

文章目录 一、引言 二、AVL树的概念 三、AVL树的插入 3、1 AVL树的简单插入 3、2 旋转分类 3、2、1 新节点插入较高右子树的右侧&#xff1a;左单旋 3、2、2 新节点插入较高左子树的左侧&#xff1a;右单旋 3、2、3 新节点插入较高左子树的右侧&#xff1a;左右双旋&#xff08…

数据库执行新增时,字段写值错乱/字段值写反了 的问题

今天给表加了个字段&#xff0c;执行新增后查看表&#xff0c;发现数据库执行新增完成后&#xff0c;字段写值错乱了&#xff0c;表现为这两个字段的值写反了↓↓↓↓↓↓ 排查了xml中所有赋值的地方&#xff0c;全都没有问题 字段与属性的通用映射&#xff1a; <resultMap…

【已解决】Java 中使用 ES 高级客户端库 RestHighLevelClient 清理百万级规模历史数据

&#x1f389;工作中遇到这样一个需求场景&#xff1a;由于ES数据库中历史数据过多&#xff0c;占用太多的磁盘空间&#xff0c;需要定期地进行清理&#xff0c;在一定程度上可以释放磁盘空间&#xff0c;减轻磁盘空间压力。 &#x1f388;在经过调研之后发现&#xff0c;某服务…

编织人工智能:机器学习发展历史与关键技术全解析

文章目录 1. 引言1.1 机器学习的定义1.2 重要性和应用场景重要性应用场景 2. 机器学习的早期历史2.1 初期理论与算法感知机决策树 2.2 早期突破支持向量机神经网络初探 3. 21世纪初期的发展3.1 集成学习方法随机森林XGBoost 3.2 深度学习的崛起卷积神经网络&#xff08;CNN&…