前言
这两天 Github 开源界发生了几件大事:
- Clash_for_windows 的作者宣布停更,原因不详;
- Clash 内核作者删库,原因不详;
- 我的账号被封,原因不详;
这可把我难受的,虽然我那仓库中的代码对开源没啥贡献,但好歹也是我从学习到工作,一步步趟过来的,承载了不少的记忆。
拥有的时候从不在意,失去之后追悔莫及。
不过好在之前有一部分代码放在了 Gitee 上,本地仓库也有一部分代码,大约有 95% 的仓库还能恢复,恢复不了的只能算了,毕竟记忆也不都是完整的,损失尚可接受。
这次号封的太突然了,事先连个邮件招呼都没有。搜索了下发现类似的情况还挺多。有尝试过找回,不过应该希望不大,好多人等了几个月最终也没有解封。
同样突然封号的事情在俄乌冲突期间也发生过,Github 当时封禁了很多俄罗斯的账号。虽说开源项目无国界,可平台政治有立场。
为了尽量避免突然封号导致的损失,将仓库代码同步到各个平台是多么重要的一件事,毕竟系统上线都还考虑异地容灾的问题。
1. 选择平台
当前代码版本控制主要使用到 Git ,而支持 Git 的主流平台大致有如下几个:
- 国外平台:Github、Gitlab;
- 国内平台:Gitee、Coding、阿里云效、极狐Gitlab;
最终我的选择是 Github、Gitlab 和 Gitee。
这么选的理由是什么?
首先,我的目标是要多个平台,且要包含国内和国外的平台。
- Github 的特点是拥有非常多的国内外开源项目,这是一定是要有的。
- Gitlab 的特点是对代码分析,CI/CD 等方面的支持比较好,并且支持自建,企业内部使用比较多,多熟悉有好处。
- Gitee 的特点是国内使用比较多,有挺多国内开源项目,访问方便且速度快。
- Coding 和 阿里云效 主要做 saas 服务,小公司一般会选择使用,不是很必要。
- 极狐Gitlab 它拥有 Gitlab 的功能,又是国内平台,这两个特点相当于 Gitlab 和 Gitee,故不必选择。
这里说一下 Gitlab 和 极狐Gitlab 的联系。
为积极响应国家“十四五规划和2035年远景目标纲要”指导精神,进一步推动中国开源、开放GitOps技术在各“产学研”领域的规范化实施和落地。
由红杉宽带跨境数字产业基金高成资本投资,成立极狐信息技术(湖北)有限公司,加上 Gitlab 官方授权的品牌技术加持,就是极狐Gitlab。
它的目标用户群体是中国大陆及港澳地区的开发者,由中国本地团队管理,服务器在中国大陆,数据中心和运营商在中国香港,因此极狐Gitlab 也被称为“中国版 Gitlab”。
OK,现在已经确定了要使用的平台,接下来就是琢磨怎么在这三个平台之间同步了。
2. 同步模式
首先要明确一点,同步是个什么需求。同步
这个词的意思并不是很清晰,既可以指一次性同步,也可以指持续性同步。那么可以细化出两种理解:
- 仓库导入(import):这是一次性同步,表示将其他平台的仓库导入到当前平台中,即完成了一次同步。导入完成后,后续如果在原平台有更新,当前平台不会同步更新。
- 仓库镜像(mirror):这表示目标仓库完全是源仓库的镜像,源仓库中有任何变化,都会反应在目标仓库中。也就是说如果在原平台有更新,当前平台也会同步更新。
很明显,我们的需求是仓库镜像(mirror)。
这里再提一嘴,Gitee 和 Gitlab 的导入(import)功能都做挺好的,它们都支持在新建项目(仓库)时,选择导入,然后登录 Github 账号,批量选择需要导入的仓库,还可以选择私有仓库,一键导入非常方便。
而 Github 就稍显弱一点了,它只能通过 URL 导入,这自然就只能导入公开仓库了,私有仓库是访问不到的。
而仓库镜像(mirror)又有两种模式:
push 模式
:把当前平台选定仓库中的代码推送到另一个平台选定的仓库中,在原仓库配置。Gitlab 和 Gitee 都支持这种模式。这个功能 Gitlab 是免费支持的,但 Gitee 是限时开放至 2023 年 12 月 31 日,届时会更新产品策略,不确定是否会变成付费功能。pull 模式
:把另一个平台选定仓库中的代码拉取到当前平台选定的仓库中,在目标仓库和源仓库配置(Webhook)。当前仅 Gitee 支持这种模式,同样的是限时开放至 2023 年 12 月 31 日。
而 Github 则不支持 push 模式,但可以通过配置 Webhook 实现 pull 模式,不过 Webhook 需要有额外的三方服务来支持处理 hook 请求,弄起来不是很方便,而且也不是非要这么做,所以这里就不细究了。
下面详细说说 push 和 poll 这两种模式。
2.1 push 模式
例如,我在 Gitlab 上创建了一个仓库sync-repo
,我想把它导入到 Github 上,同时后续如果在 Gitlab 上有新的提交,Github 也会同步提交记录。
这里我在 Gitlab 仓库初始化时勾选了自描述文件,也就是会创建 README.md 文件。
仓库创建完成,README.md
文件内容如下。
接下来在 Github 上也创建一个仓库sync-repo
,但是不创建 README.md 文件,也就是一个空仓库不包含任何文件,因为一会我们要把 Gitlab 上的 README.md 文件同步过来。
接着就需要在 Github 上创建一个私人令牌。
登录自己的 Github 账号之后,在主页右上角点击头像,选择Settings
,然后在左侧菜单最底部选择Developer settings
,再选择Personal access tokens
,点击Tokens(classic)
,接着点击Generate new token
,选择Generate new token(classic)
。
然后在弹出的对话框中填写Note
,接着勾选repo
,Expiration
那里是选择 token 的有效期,这个看个人需求,如果没有特别需求,直接就no expiration
即永不过期。
然后拉到最下面点击Generate token
,就得到了一个私人令牌,格式为ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
。
注意这里生成的 token 只会显示一次,后续就看不到了,如果忘记了只能重新生成,所以最好把这个 token 复制下来,后面会多次用到。
刚刚我们在 Github 上创建的仓库sync-repo
,复制仓库 clone 地址https://github.com/Ma-yeah/blog-images.git
,注意选择 HTTPS 协议。
然后我们回到 Gitlab 平台的sync-repo
中,在左侧菜单选择设置
,然后选择仓库
,接着展开镜像仓库
一栏,添加新的。
要填写的地方有三个:
Git 仓库 URL
:这里把刚刚复制的 Github 仓库 clone 地址粘贴过来,另外需要注意在https://
后面加上你的 Github 用户名并用@
分隔。这里我的用户名是Ma-yeah
,所以最终需要填写的是https://Ma-yeah@github.com/Ma-yeah/blog-images.git
;用户名
:这里填写的是 Github 用户名,也就是Ma-yeah
;密码
:这里填写的是刚刚在 Github 上创建的私人令牌,也就是ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
。
然后点击镜像仓库
即为保存。这样一来我们就配置好了 Github 与 Gitlab 的关联,后续如果在 Gitlab 上有新的提交,Github 也会同步提交记录。
如果网络不好,自动同步可能会有一定的延迟或者失败,此时我们可以手动同步。
同步完成后,我们回到 Github 上的sync-repo
仓库,可以看到已经同步过来了README.md
文件。
另外,如果想把 Gitlab 的仓库同步到 Gitee 上,也是同样的操作。在 Gitee 的设置中,创建私人令牌。
之后在 Gitlab 中的操作就一模一样了,这里不再赘述。
如果想要把 Gitee 上的仓库同步到 Github 上就更简单了。
在 Gitee 上的指定仓库中,选择设置
-> 仓库镜像管理
-> 添加镜像仓库
,登录了自己的 Github 账号之后,在镜像仓库
中选定要同步到 Github 上的仓库,然后在私人令牌
中填写上面的 Github 私人令牌,然后点击添加
即可。
这种模式的好处在于,可以同步私有仓库,相当于你把自家(Github)钥匙(token)给别人(Gitlab/Gitee)了,而这把钥匙可以开你家(Github)大门(公开仓库)和你的卧室门(私有仓库)。
Gitlab/Gitee 随时可以拿这个令牌主动访问 Github 上的仓库。
2.2 pull 模式
这里 pull 模式只有 Gitee 支持。例如,当我们需要把 Github 上的仓库同步到 Gitee 上时,使用了 pull 模式。
需要注意的是,这种模式下,在创建 Github 私人令牌时,不用勾选repo
,而是需要勾选admin:repo_hook
授权,也就是允许 Gitee 去 Github 的仓库中创建 Webhook。
如果 Github 的令牌没有admin:repo_hook
授权,那么就需要手动配置 Webhook。
因为 pull 模式实际上是在 Github 中填写了一个 Webhook 链接,也就是当我们向 Github 提交了代码,就会触发 Webhook 向 Gitee 发送一个 POST 请求,而 Gitee 是有相应的服务来处理这个请求的。
Gitee 就会把 Github 对应仓库重新 clone 覆盖本平台仓库。
需要注意的是,实测发现 Gitee 的 pull 模式同步延迟比较大,不过终究是会自动触发。
另外,实测发现,如果 Gitee 的仓库设置为私有时,向 github 提交代码,Gitee 不会触发自动同步,这个时候手动执行更新
即可同步。
在 Gitea(一个 Gitee 的开源版本)中,有过用户报告说私有仓库的 Webhook 存在自动触发问题。
Gitee 中的仓库镜像管理功能,在一个仓库中,只能存在一个 poll 的操作,但可以存在多个 push 的操作。
想想就可以知道为什么不能存在多个 poll 操作。因为多个源对同一个目标做覆盖(poll)这是无意义的,但可以把一个源推送(push)给多个目标,对于单个目标来说它们还是只有一个源,这并不冲突。
2.3 模式总结
值得注意的是,无论使用 push 模式还是 pull 模式,都会覆盖掉目标仓库,也就是每次触发都是全量更新的。
所以操作的时候千万要注意看清楚,别首次同步时搞错了仓库,把其他仓库的代码给覆盖了,那就找不回来了,除非你本地还有那个仓库的代码,再重新上传,否则就悲剧了,千万注意要做好备份。
3. 同步方案
通过上文的介绍,Github 原生不支持镜像仓库,所以不能直接向 Github 提交代码;Gitee 的镜像仓库只能与 Github 交互,但可以用 push 和 poll 模式;Gitlab 的镜像仓库公功能是通用的,但只能用 push 模式。
那么我们可以总结出如下几个同步方向:
- Gitlab -- push --> Github
- Gitlab -- push --> Gitee
- Gitee -- push --> Github
- Gitee <-- pull -- Github
当我们选择把代码提交到某一个平台,然后自动同步到其他平台,这个链路可以有三种:
- Gitlab -- push --> Gitee -- push --> Github
- Gitlab -- push --> Github -- pull --> Gitee
- Gitlab -- push --> Github, Gitlab -- push --> Gitee
通过上文的介绍,由于 Gitee 的仓库镜像功能是限时的,到期是否会收费未可知,不应过于依赖,因此 Gitee 只适合放在链路的末尾,即随时可以剔除而不影响其他平台,所以方案 1 被排除。
又因为 Gtiee 对于私有仓库的 Webhook 存在自动触发问题,pull 模式使用会受限,所以方案 2 也被排除。
因此,我们最后选择方案 3,即始终向 Gtilab 提交代码,然后自动向 Github 和 Gitee 推送。
结语
如此一来,Gitlab 中的所有仓库都可以设置为私有,不对外暴露,然后同步到 Github 和 Gitee 上的仓库可以选择性公开或私有,对外暴露。
完结,撒花 ✿✿ヽ(°▽°)ノ✿