社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Git

【第2623期】如何在 Monorepo 通过 Git 的 Sparse Checkout 取得部分 Repo 內容

前端早读课 • 2 年前 • 330 次点击  

前言

上周看到的一篇,应该在实际中是有实际场景的。再次感叹官方文档的重要性,遇到问题先看看官方。今日前端早读课文章由@Will 保哥授权分享。

正文从这开始~~

我们现在有越来越多的项目都是前后端分离的架构,所以在一个 Git Repo 里面同时放前后端代码是很常见的情况。不过,问题来了,如果前后端分离的很干净,若是前端人员不想要看到“后端”的原始代码,那 Git 有办法做到“部分取出”的功能吗?是的,还真的有!这篇文章我就来说说这个好用的功能。

简介 Sparse checkouts 功能

Sparse checkouts 是一个从 Git 2.25 才开始支持的功能,主要用途就是帮助你取得一个 Repo 的部分内容,大幅减少本机硬盘空间的占用,也可以帮助你更加专注在当前的开发项目。这样的机制尤其对目前 Monorepo 正夯的时候,提供一个绝佳的解决方案。

英文的 Sparse 是一个形容词,表示“稀疏的”、“零落的”的意思,代表你仅会从 Repo 取出“零星的”档案!我们从 Git 官网的 git-sparse-checkout 文件可以看到他的定义:

Reduce your working tree to a subset of tracked files

基本使用方式

而 Sparse checkouts 的使用方式,其实也就是两个步骤而已:

1、先通过 git clone 取得一个 Repo 并启用 Sparse checkouts 功能

这个动作是在复制远程储存库内容时,直接启用 Sparse checkouts 功能并套用默认样式清单,默认只会取出根目录下的文件:

git clone --filter=blob:none --sparse https://github.com/doggy8088/MonorepoAspNetCoreWithAngular.git
cd MonorepoAspNetCoreWithAngular

注意: 这个命令依然会下载完整的 Git Repo 内容,只是默认不会取出所有文件到工作目录而已!

2、启用圆锥模式 (Cone mode)

目前 Git 的 Sparse checkouts 支持两种模式,默认为 非圆锥模式 (non-cone mode),但建议改用 圆锥模式 (cone mode) 效能比较好!

git sparse-checkout init --cone

3、接着你可以通过 git sparse-checkout 明确指定你想要取得的文件夹名称

这个命令会指定取得指定文件夹下的所有文件,但在圆锥模式下,默认会包含根目录下的所有文件喔!

git sparse-checkout set "MonorepoAspNetCoreWithAngular/ClientApp"
TIPS: 快速下载超大 Repo 的小技巧

你可以在 git clone 的时候套用 --depth 1 命令,仅取得最近 1 个版本的相关 Blob 物件,这样就可以大幅缩短 git clone 的时间。我以 ASP.NET Core 原始码项目为例,正常的 git clone 在高速网路下也要十几秒才能下载完毕,但通过以下命令就只要 2 秒就可以复制完毕:

git clone --depth 1 --filter=blob:none --sparse https://github.com/dotnet/aspnetcore.git
cd aspnetcore

注意: 使用 --sparse 默认就只会取出 (Checkout) 根目录下的所有文件而已,但沒有任何「子文件夹」喔。

然而,你若只想取回 /docs 文件夹的話,就只要用以下命令即可立即下载这个文件夹下的用到的 Blob 物件,速度極快:

git sparse-checkout set "/docs"

圆锥模式简介

Git 的 Sparse checkouts 支持两种模式, 非圆锥模式 (non-cone mode) 与 圆锥模式 (cone mode),主要差別在于解析 路径样式清单 (Pattern Set) 的格式不同!

事实上,你使用 git sparse-checkout 所做的任何操作,都会记录在一个 .git/info/sparse-checkout 设置文件中,這是一个文本文件 (Text file),內容跟 .gitignore 的格式有点相似,但你要特別注意在不同的模式下,其內容所代表的意义是不同的!

非圆锥模式 (non-cone mode)

先说,虽然这是 Git 的默认值,不过不建议使用,主要是效能考量!🔥

在 非圆锥模式 下,这个 .git/info/sparse-checkout 设置文件的内容会采用 FULL PATTERN SET 语法,其内容格式与 .gitignore 完全一样。

那什么是 FULL PATTERN SET 呢?简单来说,就是这些 Patterns 是对整个 Repo 的文件路径进行比对,所以你可以用“正向比对”,也可以用 ! 进行“反向比对”,设置上比较灵活。不过,这层灵活性的唯一的缺点就是效能较差,因为当 Git 在做 Checkout 动作时,每一个文件在取出时,每一条规则都要判断,所以复杂度是 O(M*N) 这么多,这意味着文件越多或规则集越多,取出(Checkout)的速度就越慢!

我举个简单的例子,以下列命令为例,该项目默认使用了非圆锥模式,然后指定了 MonorepoAspNetCoreWithAngular/ClientApp 路径。事实上,这个 MonorepoAspNetCoreWithAngular/ClientApp 所代表的意义,是指“所有目录与子目录下有包含 MonorepoAspNetCoreWithAngular/ClientApp 的路径,都在取出的范围内”。

git sparse-checkout set "MonorepoAspNetCoreWithAngular/ClientApp"

你如果设定 /MonorepoAspNetCoreWithAngular/ClientApp 路径,就代表著只有“位于根目录下的 /MonorepoAspNetCoreWithAngular/ClientApp 路径,才包含在取出范围内”。

git sparse-checkout set "/MonorepoAspNetCoreWithAngular/ClientApp"
圆锥模式 (cone mode)

在 圆锥模式 下,这个 .git/info/sparse-checkout 设置文件的内容会采用 CONE PATTERN SET 语法,这个语法只能说近似于 .gitignore 的格式,但比对上稍微再严格一些,而且有些特殊的规则。

基本上圆锥模式下的 CONE PATTERN SET 规则集有两大特性:

  • Recursive: 你所指定的路径,默认包含所有的子目录下的所有文件路径。

  • Parent: 你所指定的路径所在的目录下的所有文件也都包含在内!(有点绕口,需要思考一下)

我举个简单的例子,以下列命令为例,我将该项目启用了圆锥模式,然后指定了 MonorepoAspNetCoreWithAngular/ClientApp 路径:

git clone --filter=blob:none --sparse https://github.com/doggy8088/MonorepoAspNetCoreWithAngular.git
cd MonorepoAspNetCoreWithAngular
git sparse-checkout init --cone
git sparse-checkout set "MonorepoAspNetCoreWithAngular/ClientApp"

这个 Pattern 将会包含:

Recursive: 包含所有子目录所有路径 (MonorepoAspNetCoreWithAngular/ClientApp/**)
Parent: 包含上层的 /MonorepoAspNetCoreWithAngular/*
 与 /* 目录下的所有文件

所以我们可以说,以下圆锥模式的样式集(CONE PATTERN SET):

MonorepoAspNetCoreWithAngular/ClientApp

会等同于以下非圆锥模式的样式集(FULL PATTERN SET):

/*                                          根目录所有档案
!/*/
排除根目录下的所子目录 (没有排除档案)
/MonorepoAspNetCoreWithAngular/ 包含这个子目录以及底下所有路径(目录+档案)
!/MonorepoAspNetCoreWithAngular/*/ 排除这个子目录下的所有子目录 (没有排除档案)
/MonorepoAspNetCoreWithAngular/ClientApp/ 包含这个子目录以及底下所有路径(目录+档案)

在圆锥模式下,你无法排除已经包含在这些 Pattern Set 在内的所有文件。

如果你真的想要精准的包含与排除文件,只能使用非圆锥模式 (non-cone mode)!

为什么要取名叫圆锥模式?

我从 Bring your monorepo down to size with sparse-checkout 文章中撷取两张图片来说明。

假设你的 Monorepo 有以下目录结构:

若你只想取出 /client/android 目录下的源码,那么你若用圆锥模式的话,就只要用一条规则就可以取出你要的档案:

git sparse-checkout set "client/android"

你从这个文件取出的模式来看,整个文件夹结构就好像一个“圆锥体”,而取得文件的方式是从上到下以“圆锥状”的方式取出,圆锥的顶端就是项目的“根目录”,而之后每一层的档案也都需要取出,一直取到某一层之后,就会取出以下的所有档案。

我只能说取名是一种艺术,大家要多发挥想像力!😄

常用 Sparse checkouts 命令与参数

1、启用 Sparse checkouts 功能

# 启用非圆锥模式 (non-cone mode)
git sparse-checkout init

# 启用圆锥模式 (cone mode)
git sparse-checkout init --cone

2、取得 Sparse checkouts 的路径样式清单

git sparse-checkout list

注意: 如果你的 Repo 并没有启用过 Sparse checkouts,第一次使用会出现 fatal: this worktree is not sparse 错误信息。

3、设定 Sparse checkouts 的路径样式清单 (.git/info/sparse-checkout)

使用 git sparse-checkout set 命令会直接覆盖现有的路径清单:

git sparse-checkout set "/MonorepoAspNetCoreWithAngular/ClientApp"
git sparse-checkout list

执行完 git sparse-checkout set 命令之后,你的工作目录下所有文件就会立即反应出结果,执行前请先确认拥有一个干净的工作目录!

你可以使用以下命令调整 Sparse checkouts 回覆到默认值:

git sparse-checkout set ""
git sparse-checkout list

无论你使用哪种 Sparse 模式,执行完之后预设都只会剩根目录下的档案!

4、一次设定多组 Sparse checkouts 的路径样式清单

设定多组 Sparse checkouts 路径样式时,套用顺序很重要!

git sparse-checkout set "!/*" "/MonorepoAspNetCoreWithAngular/ClientApp" ".git*"
git sparse-checkout list

此范例仅适用于非圆锥模式!(FULL PATTERN SET)

5、加入新路径到 Sparse checkouts 的路径样式清单

git sparse-checkout set "!/*" "/MonorepoAspNetCoreWithAngular/ClientApp"
git sparse-checkout add ".git*"
git sparse-checkout list

此范例仅适用于非圆锥模式!(FULL PATTERN SET)

6、重新套用 Sparse checkouts 的路径样式清单

这个命令仅用于你手动调整 .git/info/sparse-checkout 设定档内容之后执行。

git sparse-checkout reapply

7、停用 Sparse checkouts 功能

这个命令会将所有工作目录中的档案完整取出:

git sparse-checkout disable

注意: 此命令不会更动 .git/info/sparse-checkout 设定档中的路径样式清单。

8、将 Sparse checkouts 功能切换至圆锥模式 (cone mode)

git sparse-checkout disable
git sparse-checkout init --cone
#git sparse-checkout set
git sparse-checkout list

由于圆锥模式与非圆锥模式的 Patterns 并不相容,切换过程记得要重新检视过!

将 Sparse checkouts 功能切换至非圆锥模式 (non-cone mode)

git sparse-checkout disable
git sparse-checkout init
#git sparse-checkout set
git sparse-checkout list

由于圆锥模式与非圆锥模式的 Patterns 并不相容,切换过程记得要重新检视过!

相关连结

  • Git - git-sparse-checkout Documentation

  • Bring your monorepo down to size with sparse-checkout | The GitHub Blog

  • Highlights from Git 2.25 | The GitHub Blog

  • Partial clone | GitLab

  • Monorepo vs. Polyrepo

关于本文
作者:@Will 保哥
原文:https://blog.miniasp.com/post/2022/05/17/Down-size-your-Monorepo-with-Git-Sparse-checkouts

相关阅读,欢迎自荐投稿,前端早读课等你来。


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/134959
 
330 次点击