跳至主要內容

各代码平台仓库同步

Mayee...大约 11 分钟

前言

这两天 Github 开源界发生了几件大事:

  • Clash_for_windows 的作者宣布停更,原因不详;
  • Clash 内核作者删库,原因不详;
  • 我的账号被封,原因不详;
suspended
suspended

这可把我难受的,虽然我那仓库中的代码对开源没啥贡献,但好歹也是我从学习到工作,一步步趟过来的,承载了不少的记忆。

拥有的时候从不在意,失去之后追悔莫及。

不过好在之前有一部分代码放在了 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 文件。

01_2
01_2

仓库创建完成,README.md文件内容如下。

01_2
01_2

接下来在 Github 上也创建一个仓库sync-repo,但是不创建 README.md 文件,也就是一个空仓库不包含任何文件,因为一会我们要把 Gitlab 上的 README.md 文件同步过来。

02_2
02_2

接着就需要在 Github 上创建一个私人令牌。 登录自己的 Github 账号之后,在主页右上角点击头像,选择Settings,然后在左侧菜单最底部选择Developer settings,再选择Personal access tokens,点击Tokens(classic),接着点击Generate new token,选择Generate new token(classic)。 然后在弹出的对话框中填写Note,接着勾选repoExpiration那里是选择 token 的有效期,这个看个人需求,如果没有特别需求,直接就no expiration即永不过期。 然后拉到最下面点击Generate token,就得到了一个私人令牌,格式为ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。 注意这里生成的 token 只会显示一次,后续就看不到了,如果忘记了只能重新生成,所以最好把这个 token 复制下来,后面会多次用到。

02_2
02_2

刚刚我们在 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
02_2
02_2

然后点击镜像仓库即为保存。这样一来我们就配置好了 Github 与 Gitlab 的关联,后续如果在 Gitlab 上有新的提交,Github 也会同步提交记录。 如果网络不好,自动同步可能会有一定的延迟或者失败,此时我们可以手动同步。

02_2
02_2

同步完成后,我们回到 Github 上的sync-repo仓库,可以看到已经同步过来了README.md文件。

02_2
02_2

另外,如果想把 Gitlab 的仓库同步到 Gitee 上,也是同样的操作。在 Gitee 的设置中,创建私人令牌。 之后在 Gitlab 中的操作就一模一样了,这里不再赘述。

02_2
02_2

如果想要把 Gitee 上的仓库同步到 Github 上就更简单了。 在 Gitee 上的指定仓库中,选择设置 -> 仓库镜像管理 -> 添加镜像仓库,登录了自己的 Github 账号之后,在镜像仓库中选定要同步到 Github 上的仓库,然后在私人令牌中填写上面的 Github 私人令牌,然后点击添加即可。

02_2
02_2

这种模式的好处在于,可以同步私有仓库,相当于你把自家(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授权,那么就需要手动配置 Webhookopen in new window

02_2
02_2

因为 pull 模式实际上是在 Github 中填写了一个 Webhook 链接,也就是当我们向 Github 提交了代码,就会触发 Webhook 向 Gitee 发送一个 POST 请求,而 Gitee 是有相应的服务来处理这个请求的。 Gitee 就会把 Github 对应仓库重新 clone 覆盖本平台仓库。

02_2
02_2

需要注意的是,实测发现 Gitee 的 pull 模式同步延迟比较大,不过终究是会自动触发。 另外,实测发现,如果 Gitee 的仓库设置为私有时,向 github 提交代码,Gitee 不会触发自动同步,这个时候手动执行更新即可同步。 在 Gitea(一个 Gitee 的开源版本)中,有过用户报告说私有仓库的 Webhook 存在自动触发问题open in new window

02_2
02_2

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

当我们选择把代码提交到某一个平台,然后自动同步到其他平台,这个链路可以有三种:

  1. Gitlab -- push --> Gitee -- push --> Github
  2. Gitlab -- push --> Github -- pull --> Gitee
  3. Gitlab -- push --> Github, Gitlab -- push --> Gitee

通过上文的介绍,由于 Gitee 的仓库镜像功能是限时的,到期是否会收费未可知,不应过于依赖,因此 Gitee 只适合放在链路的末尾,即随时可以剔除而不影响其他平台,所以方案 1 被排除。 又因为 Gtiee 对于私有仓库的 Webhook 存在自动触发问题,pull 模式使用会受限,所以方案 2 也被排除。

因此,我们最后选择方案 3,即始终向 Gtilab 提交代码,然后自动向 Github 和 Gitee 推送。

02_2
02_2

结语

如此一来,Gitlab 中的所有仓库都可以设置为私有,不对外暴露,然后同步到 Github 和 Gitee 上的仓库可以选择性公开或私有,对外暴露。


完结,撒花 ✿✿ヽ(°▽°)ノ✿