背景
你是否好奇类github平台式代码治理平台背地的运作原理,上面咱们一起探索并着手开发属于本人的GitHub
市面上可供咱们部署私人git服务的开源我的项目有以下几种
我的项目 | 开发语言 | 地址 |
---|---|---|
gitlab | ruby | https://gitlab.com/gitlab-org... |
gogs | go | https://github.com/gogs/gogs |
gitea | go | https://github.com/go-gitea/g... |
上面是我在应用这些我的项目搭建私人git服务时遇到的问题
- gitlab对机器性能有肯定要求,像树莓派(
我的4b[4G]
)这种零碎装置后,常常会卡死机,装置要求详见:https://docs.gitlab.cn/jh/ins...- gogs运行对机器性能要求不高,然而基于go语言开发的,作为前端开发者不利于二次性能扩大
- gitea是基于gogs的开发的
我的项目
本着对技术的探索精力和反复造轮子的激情,于是着手打造一个对前端开发者敌对的git代码治理平台[随心码]
开源地址:https://github.com/lzuntalented/lz-git
示例网站:http://git.lzz.show/lz/lz-git
原理刨析
其实这些平台的实质是近程执行git命令,咱们在页面的操作或者本地执行git的命令,都是向远端服务器发送了申请,并附带申请内容,这些平台帮咱们在服务器执行git命令
例如:当咱们在页面上创立一个我的项目时,理论就是在服务器上执行了git init
命令
如果你装置了git,通过命令git clone dir
(dir指本地任意git我的项目的目录门路)克隆一个仓库,在dir
目录下中能够进行git
的所有命令操作
实现
技术
我的项目构造:lerna
前端:Typescript + react + antd
后端:Nestjs + mysql
我的项目架构
创立我的项目
咱们能够通过命令git init --bare [repositories]
创立一个空仓库,在多人合作时,当作仓库核心
例如创立一个blog
仓库,执行命令git init --bare blog.git
在服务器上不须要存储工作目录,通过--bare
参数创立一个空的仓库(如下图上方的红色框内容)
咱们平时在克隆我的项目时,本地目录下会多一个.git
暗藏目录,通过--bare
参数创立的仓库没有.git
目录,而是间接把.git
目录下的内容开展在以后仓库目录下,同时不会有工作文件
能够察看到咱们在仓库名前面加了.git
,这个其实没太多含意,只是示意是git仓库而已,像咱们从GitHub上克隆我的项目时能够发现,他们提供的克隆地址也是带.git,为了雷同而已
拉取和推送代码
因为要部署在远端服务器,无奈通过克隆dir的形式,所以咱们应用http模式的克隆形式
# 体验示例站点克隆我的项目性能git clone http://git.lzz.show/lz/lz-git.git
那咱们在执行git clone
命令时产生了什么事件呐,参见:https://git-scm.com/docs/http...
- 向远端发送一个门路为
/info/refs?service=git-upload-pack
的GET申请,以获取远端仓库的援用信息- http服务承受到这个申请后,在远端仓库下执行命令
git upload-pack --stateless-rpc --advertise-refs remote/repository/dir
,并把命令输入作为http的响应返回给客户端- 客户端发动门路为
/git-upload-pack
的POST申请,以获取远端资源- http服务承受到这个申请后,在远端仓库下执行命令
git upload-pack --stateless-rpc remote/repository/dir
,并把命令输入作为http的响应返回给客户端- 至此命令执行结束
git push命令执行时与clone命令流程相似,只是service
参数由git-upload-pack
变成git-receive-pack
,git命令参数由upload-pack
变为receive-pack
问题记录
因为git发动的http申请header中Content-Type为非标准头,express无奈主动解析申请体里的body,须要咱们自定义中间件以解析body
export function header(req: Request, res: Response, next: NextFunction) { if (req.header('Content-Type'.toLowerCase()) === 'application/x-git-upload-pack-request' || req.header('Content-Type'.toLowerCase()) === 'application/x-git-receive-pack-request' ) { const body = []; req.on('data', (chunk) => { body.push(chunk); }).on('end', () => { // body转换成buffer格局利于将body内容作为输出传入git命令中 req.body = Buffer.concat(body); next(); }); } else { next(); }};
最初
至此,咱们初步构建了一个基于Javascript开发的git代码治理平台,后续咱们持续向Github看齐并欠缺性能
如果您感觉这篇文章对您有用,欢送留一赞
也欢送给我的项目点⭐开源地址
历史我的项目
- 【随心秀】开篇 - 开源微场景编辑器介绍
- 从零开始-根底流程图编辑库