1 Git原理
版本控制体系在软件开辟和团队协作中扮演着至关告急的脚色。它们资助开辟职员跟踪和管理代码的厘革,调和多人同时编辑同一代码库,回溯汗青版本,并办理代码辩说等标题。Git作为当今最盛行的分布式版本控制体系,为开辟职员提供了强大的功能和机动性。
本次报告的主题将聚焦于Git原理、Gitflow与多人协作。我们将深入分析Git的工作原理、焦点概念。
1.1 Git Objects
我们从git一次提交作为切入点,即”git add .“,”git commit -m ”xxx“”。
这份很显着一眼看已往就是hash值的文件名./44/baf5debd9a38f0d3bb41c05167ab3da0f9ffdf是怎么回事呢?实行阅读一个文件,会发现都是乱码,这是由于这些都是二进制文件。
git提供了详细的查察方式。对于这个文件,我们可以得出,hash值为44ba 开头的文件,生存着blob范例的文件内容。- $ git cat-file -p 44baf5debd9a38f0d3bb41c05167ab3da0f9ffdf # 查询文件内容
- ...一堆内容
- $ git cat-file -t 44ba #查询文件类型
- blob
复制代码 我们得到了我们第一个Git Objects,blob范例,生存文件内容的二进制文件块。在此底子上,我们以此类推可以得出其他被我们通过git add下令添加到暂存区的Git Objects。
按照正常使用流程,我们现在应该实行commit下令,我们实行实行commit下令,再看看有什么厘革。会发现,多了两个新文件。
我们用同样的方式查察此中一个的内容,那么我们现在打仗到了第二种范例的git objects,tree范例的Git Objects生存了一个commit内的文件信息,这些文件信息包罗文件权限、文件名。
现在的关系可以用下边的图表现。
而另一个,生存着commit的信息,这是第三种Git Objects范例,包罗了作者信息、commit者信息、commit内容和commit对应树的信息。
此时的关系图如下:
我们目条件交的文件都是根目次下文件,没有实行过文件夹里的和文件夹里的文件夹里的(嵌套)文件。为了方便各人明白,我们实行添加两个文件。- git add .\.vscode
- git commit -m "test for dir"
复制代码
这次走完,我们观察一下天生的Git Objects。本轮commit天生了367B、20ac、30d7、4172、64c7、- $ git cat-file -p 367b
- tree 20ac6ca38672867522c310d493ac2b74d65be4fa
- parent 873e351820080142fc41bb090bb9a8550d2fd3eb
- author Bugyalu.W <xxx> 1689058165 +0800
- committer Bugyalu.W <xxx> 1689058165 +0800
-
- test for dir
- $ git cat-file -p 20ac
- 040000 tree 4172f27bc0e6b61e60129e511683b1b040f284e1 .vscode
- 100644 blob c924a6e0fc4c36bad6f23cb87ee59518c771f936 read-cache.c
- 100644 blob 44baf5debd9a38f0d3bb41c05167ab3da0f9ffdf read-tree.c
- $ git cat-file -t 30d7
- blob
- $ git cat-file -t 30d7
- 1
- $ git cat-file -t 4172
- tree
- $ git cat-file -p 4172
- 100644 blob 85c2121b25dcaa4a1ca47a24426a34857ad1644d settings.json
- 040000 tree 64c71c93d26b15d984ef1c805c69cd35c9c5348c test
- $ git cat-file -t 64c7
- tree
- $ git cat-file -p 64c7
- 100644 blob 30d74d258442c7c65512eafab474568dd706c430 .gitkeep
- $ git cat-file -t 873e
- commit
- $ git cat-file -p 873e
- tree 5e02d2b86614f47a35239d1c9726f6b68bd95b5c
- author Bugyalu.W <xxx> 1689058072 +0800
- committer Bugyalu.W <xxx> 1689058072 +0800
- test
复制代码 只看上边这份玩意儿着实是爆炸,以是我继续拉了一份关系图。可以发现,全部的文件夹都将作为一个tree节点,作为子树存在。
同时你会发现,我们新提交的commit,其内容中多了一个parent ,指向了上一个commit节点。
1.2 Git分区
Git的三个焦点分区指的是:堆栈、suoyin区、工作区三个分区。
1.2.1 堆栈
堆栈是哪一部分呢?
这个时间就扳连出一个标题,起首我们知道git是支持多分支的,这意味着我们的关系图还可以继续增补,那么git是怎么处理处罚这一块的呢?
这里就不是objects的内容了,我们来到.git根目次,可以发现其包罗一个HEAD文件。
查察文件内容,很容易发现这里生存着指向当前分支的指针。
相应的,我们查察master文件,得到一串hash字符串,对比我们的关系图会知道,这个hash字符串相称于指着我们最新的commit,于是我们可以继续绘制出关系图。
为了让关系图表现得更显着,我们可以实行创建而且切换到main分支。- git branch main
- git checkout main
复制代码 此时objects文件夹中文件没有厘革,新增了refs/heads/main,HEAD出现厘革,可以据此得出最新的关系图。
那么综上所述,我们现在知道了git是怎么存储分支、文件内容、目次布局和commit信息的啦。
1.2.2 索引区
起首,我们要知道索引区和暂存区概念的差别。
暂存区是Git用于准备提交的更改的中心地区。暂存区包管了我们对工作区中的文件举行修改后,这些更改并不会立刻被提交到堆栈中,你可以对这部分文件做更精致的编削后再举行commit。
而索引区,包罗了暂存区,也包罗了当前commit全部blob类节点的索引。
git的索引区生存在根目次的index文件,实行查察它,发现这是一个二进制文件。
由于它不是一个Git Objects,我们不能通过cat-file下令查察,而应该使用ls-files,该下令专门用来查察index文件。
会发现,git的暂存区文件生存了全部待提交(即已经add,但是没有commit)的文件和全部已提交的文件,包罗了它们的hash值和文件路径文件名。
如果我们把全部暂存的文件取消暂存,再次查察index索引文件,就会发现,此时剩下四个文件,这四个文件正是我们上一张关系图中四个blob型git objects。- $ git ls-files --stage
- 100644 85c2121b25dcaa4a1ca47a24426a34857ad1644d 0 .vscode/settings.json100644 30d74d258442c7c65512eafab474568dd706c430 0 .vscode/test/.gitkeep100644 c924a6e0fc4c36bad6f23cb87ee59518c771f936 0 read-cache.c 100644 44baf5debd9a38f0d3bb41c05167ab3da0f9ffdf 0 read-tree.c
复制代码 也就是说,index文件相称于一个待形成的新commit节点,里边包罗了一个commit范例Git Object的部分信息,但差别的是,这里生存的是纯blob节点,并没有tree节点。我们由此别的绘制一份关系图。
我们实行修改30d7,也就是现在的.gitkeep文件,并将它添加到暂存区。此时观察index厘革。会发现,此时index中本来的.gitkeep文件,指向的blob节点更新了,从30d7改向了e2e1。此时的关系图如下,相称于本来指向30d7的指针现在指向了e2e1.- $ git ls-files --stage
- 100644 85c2121b25dcaa4a1ca47a24426a34857ad1644d 0 .vscode/settings.json 100644 e2e107ac61ac259b87c544f6e7a4eb03422c6c21 0 .vscode/test/.gitkeep 100644 c924a6e0fc4c36bad6f23cb87ee59518c771f936 0 read-cache.c100644 44baf5debd9a38f0d3bb41c05167ab3da0f9ffdf 0 read-tree.c
复制代码
如果我们再实行commit,此时查抄index没有厘革,但是我们的关系图现在出现成下图。- git commit -m "change .gitkeep"
复制代码
我们发现和前次commit有这些差别:
- Git根据当前索引index,新天生了一个commit节点。
- HEAD指向的当前分支指针厘革,指向了新天生的commit节点。
- 凡是涉及到.gitkeep文件的tree节点的hash都发生了厘革。
1.2.3 工作区
末了一个概念是工作区,工作区指的是在我们电脑上的文件本身,这个概念在git中是最单薄的,由于我们对工作区的使用着实就是我们一样寻常工作中对文件的使用,在我们真正实行git下令之前,这部分工作区的内容不会在git堆栈和索引区中表现。
1.3 数据完备性与包文件压缩
在上边的一系列原理中,我们有提到一嘴git堆栈中有很多哈希文件,这涉及到git另一个知识点。
诸位有没有想象过,如果真的用一个堆栈完备生存一个项目从零到一的全部文件,那这份堆栈会有多大,会有多大?
以是显然,肯定要采取一些压缩机制。
上文中出现的哈希值,都是泉源于Git对于SHA-1哈希算法的应用,Git在天生差别的Git Object时,都会有其哈希值的盘算的过程,hash值将作为Git Object节点的唯一标识。这些节点互干系联,从关系图中很容易看出这是一根哈希树。
根据这些哈希值,一方面可以在objects文件夹中找到差别的Git Object,而此中的blob范例object,即生存着文件的实际内容,另一方面,通过SHA1哈希算法和哈希树的机制包管了汗青纪录不可篡改,由于当你修改了某个节点,那么与之干系的tree节点、commit节点再到commit节点之后全部的节点的hash值都应该厘革,很容易发现标题。
这些object节点,通过zlib算法对对象内容举行压缩,通过hash值比力的方式来确保重复内容只存贮一次,淘汰存储占用。而在使用时,又可以通过解压算法还原出本来的内容。
除却这些使用外,git还引入了进一步压缩的方式。看到上边的关系图,我们会发现在当前commit中,出现了一个blob节点不在树上的环境。
长此以往,这里就出现了优化空间,由于部分blob节点大概很长时间内不再使用,属于冷数据。那么git就对此做了优化,git会定期把疏松对象文件打包成包文件(packfile),进一步淘汰文件碎片。根据对象存储方式,可分为loose object和packed object。loose object 是单独文件的疏松对象,packed object 则是存在于包文件中的压缩对象。Git会在两种对象间转换,以优化堆栈存储。
2 Gitflow流程与模式
2.1 Git flow
起首,来看一下尺度的git flow演示图。
图片泉源:《字节研发办法下的 Git 工作流》
这一串复杂的流程,就是最经典的gitflow工作流,Git flow。
在这个流程中,Git flow订定了非常严酷的分支管理规则,分支被区分为:
- master(主分支):用于发布新版本,在这里打tag作为版本。
- develop(开辟分支):用于集成各种功能分支,是一个较稳固的开辟进度分支。
- feature(特性分支):feature分支的源分支是develop分支,全部新功能开辟都通过专门的特性分支(feature branch)来开辟,开辟完成后归并回develop分支。feature分支是多分支,定名上参考”feature/xxx“,在归并后删除天职支。
- hotfix(告急修复分支):线上代码出现严峻Bug须要告急修复时使用该分支。hotfix分支劈头于master分支(也就是线上代码),开辟完成后归并至master分支同时归并到develop分支以确保下一个版本的代码也包罗这个hotfix补丁。hotfix分支是多分支,定名上参考”hotfix/xxx“,在归并后删除天职支。
- bugfix(标题修复分支):专门用于修复开辟环境的bug,源分支是develop分支,终极也归并到develop分支。bugfix分支是多分支,定名上参考”bugfix/xxx“,在归并后删除天职支。
- release(发布分支):当develop分支代码测试完毕,准备发布时,将从develop分支发起release分支,进入release阶段的代码将不允许新特性的添加(也就是不允许feature分支归并入develop分支大概release分支)。release分支将举行终极最严酷的测试。release分支担当为了修复bug而产生的提交。release分支一连变动,直至开辟工作验收通过,这时release分支将会打上版本tag归并至master分支同时归并至devlop分支以确保develop分支是master分支的直接后继。release分支是多分支,定名上参考”release/xxx“,在归并后不肯定须要删除天职支。
Git flow的上风和劣势黑白常显着的,其优点:
- 分支各司其职,能覆盖大部分开辟场景。
- 预期master分支中的任何commit都可摆设,在出现事故时对于回滚非常友好。
- 严酷按照流程实行,出现巨大事故的情况会大大低落。
其劣势同样很大:
- 过于繁琐,无法要求全部团队成员按照这个流程严酷实行。
- 对一连摆设和敏捷开辟并不友好。
2.2 Github Flow
Github Flow一种相对更轻量的工作流。其焦点概念是Pull Request(简称PR),须要注意的是,PR并非git提供的本领而是Github提供的本领,其夸大多堆栈、强CR。
图片泉源:《字节研发办法下的 Git 工作流》
一样平常来讲,Github Flow工作流只有一个主分支(Master)是固定的,且受掩护的,只有特定权限的人才可以向master分支合入代码。
在Github Flow中,我们一样平常来讲须要fork源堆栈,在新堆栈(注意,Github同样支持本堆栈内分支和分支之间的PR)中举行代码提交(一样平常提交到主分支),当全部的功能开辟完毕,则通过PR提交一份形貌信息和代码,关照源堆栈开辟者举行CR,确认无误后,将由源堆栈开辟者将代码合入主分支。
Github Flow 优点是相对于 GitFlow 来说比力简朴,同时由于每次PR都会同步提交形貌信息,可以获取更多节点信息,其缺点是由于只有一条 Master 分支,万一代码合入后,由于某些因素 Master 分支不能立刻发布,就会导致终极发布的版本和筹划差别。
2.3 Gitlab Flow
Gitlab Flow 是 Git Flow 与 Github Flow 的联合。它汲取了两者的优点,既有顺应差别开辟环境的弹性,又有单一分支的简朴和便利。
我们在Github Flow中提到了PR,而在Gitlab堆栈中,有个雷同的使用,叫Merge Request(MR)——这两者着实没什么区别,引用某阿里大佬的表明:
- 在 Github 上也可以玩分支模式,提交归并哀求同样用 Pull Request。
- 在 Gitlab 上也可以玩 fork 模式,提交归并哀求照旧 Merge Request。
同时,相比Github flow,GitLabFlow 增长了对预生产环境和生产环境的管理,即 Master 分支对应为开辟环境的分支,预生产和生产环境由其他分支(如 Pre-Production、Production)举行管理。
在这种环境下,Master 分支是 Pre-Production 分支的上游,Pre-Production 是 Production 分支的上游。
GitlabFlow 规定代码必须从上游向卑鄙发展:
- 即新功能或修复 Bug 时,特性分支的代码测试无误后,必须先合入 Master 分支
- 然后才气由 Master 分支向 Pre-Production 环境合入
- 末了由 Pre-Production 合入到 Production。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金 |