这篇讲内网 GitLab 上的公开、内部和私有项目,分别怎么搬到 AngusGit。看完你可以按可见性(谁能看到仓库)选择导入或推送,把多层子组定成「团队/仓库名」,再用git clone --bare加git push --all和--tags推进空仓库,并用git ls-remote对比两边是否一致。
先登录 AngusGit。公开项目在侧栏仓库点导入仓库。仓库 URL填项目页克隆里的 HTTPS 地址,不要填 SSH。所有者选团队,仓库名称按下一节的路径规则填,名称只能用中文、字母、数字、连字符和下划线。只给内部看时打开设为私有仓库。这三项填完,开始导入才能点。
推送前在我的 → 访问令牌点生成新令牌,密码验证填登录密码,勾git:write,仓库权限WRITE,生成后马上复制。用户名填登录名,密码填令牌。先手动成功推一个仓库,在系统凭据窗口里保存,后面的批量脚本才不会每行都问密码。改用 SSH 时,没有~/.ssh/id_ed25519.pub就执行ssh-keygen -t ed25519 -C "you@example.com",把cat ~/.ssh/id_ed25519.pub的那一行登记到我的 → SSH密钥。用户名是git,端口是 2222。
下文的 GitLab 地址用https://gitlab.example.com/platform/backend/order-service.git举例:platform是群组,backend是子组,order-service是项目,换成你自己的路径即可。公开仓库导入长什么样,看已经导入的xlliu/hello-world-import:只有main和一条提交。整个团队怎么双跑和回滚,见文末的 GitLab 迁移清单一文。
1. 先看 GitLab 项目的可见性
项目页名称旁边、或设置 → 通用 → 可见性里,三种的差别如下:
| GitLab 可见性 | 不登录能读吗 | 在 AngusGit 上用哪条路 |
|---|---|---|
| 公开 | 能 | 只要当前代码:导入仓库。要保留历史:推送 |
| 内部 | 不能,要登录 GitLab | 推送 |
| 私有 | 不能,要是项目成员 | 推送 |
判断方法很简单:打开浏览器的无痕窗口,不登录访问项目页,能看到代码才能用导入。
2. 公开项目:直接导入
侧栏点仓库→ 右上角导入仓库,仓库 URL填 GitLab 项目页克隆里的 HTTPS 地址,不要填 SSH 地址,因为 AngusGit 服务器上没有你的 SSH 密钥。同一张表单导入公开仓库的结果,见 GitHub 上的 Hello-World 导入成的xlliu/hello-world-import。
真正去拉代码的是 AngusGit 服务器,它要能访问那台 GitLab。导入只带默认分支当时的文件;源分支叫master时,AngusGit 上的分支名仍是main。表单按开头填写:仓库 URL、所有者、仓库名称,需要时打开设为私有仓库。
3. 定好路径怎么对应
GitLab 的项目可以放在多层群组下面,例如platform/backend/order-service。AngusGit 的仓库地址只有两级:所有者(个人或团队)加仓库名,所以整批项目都要按同一条规则对应过去。常见的两种对应方式:
| GitLab 路径 | 方式一:一级群组对应团队 | 方式二:子组并进仓库名 |
|---|---|---|
platform/backend/order-service | platform/order-service | platform/backend-order-service |
platform/frontend/order-web | platform/order-web | platform/frontend-order-web |
方式一的地址短,但不同子组下有同名项目时会撞名。方式二不会撞名,地址稍长。拿不准就用方式二。
还要检查项目名里有没有点号。AngusGit 的仓库名只能用中文、字母、数字、连字符和下划线,点号会被去掉,例如docs.site要提前改成docs-site。
4. 私有和内部项目:克隆后推送
在 AngusGit 建团队和空仓库
按第 3 节定好的规则,先在 AngusGit 建好团队,再在团队下建同名的空仓库。新建仓库时,添加 README 文件、添加 .gitignore、选择许可证三项都不要勾选。任何一项勾上,仓库就不再是空的,推送时会被拒绝。
从 GitLab 完整克隆
用你自己的 GitLab 账号克隆。GitLab 开了双因素认证时,HTTPS 的密码一栏要填 GitLab 的个人访问令牌,权限勾选
read_repository就够了。--bare会把 GitLab 上的所有分支和标签都拉下来,不生成工作区。主分支叫 master 时先改名
AngusGit 新建的空仓库默认分支是
main。GitLab 项目的主分支叫master时,先在本地改名;已经是main就跳过。改名之后,团队成员的本地习惯、GitLab CI 里写死的分支名,都要跟着改成main。推送所有分支和标签
第一行推所有分支,第二行推所有标签。HTTPS 的用户名填 AngusGit 登录名,密码填一把勾了
git:write的访问令牌。用 SSH 地址也可以。
对应的完整命令如下。gitlab.example.com和platform/backend-order-service都要换成你的地址,并先建成空仓库。主分支已经叫main时,跳过git branch -m。推送用的 HTTPS 地址换成你的空仓库;私有仓库克隆时会要访问令牌,按开头生成git:write令牌,不要把令牌写进文章或截图。
gitclone--barehttps://gitlab.example.com/platform/backend/order-service.gitcdorder-service.gitgitbranch-mmaster maingitpush https://git.anguskit.com/platform/backend-order-service.git--allgitpush https://git.anguskit.com/platform/backend-order-service.git--tags--bare得到的是裸仓库:只存 Git 数据,没有可编辑的工作区,正好用来原样转推。为什么不用--mirror?--mirror会把远程的所有引用都拉下来,包括 GitLab 为每条合并请求保存的refs/merge-requests/*。之后再git push --mirror,这些引用会原样出现在 AngusGit 仓库里,既没用,还会干扰分支列表和统计。--bare配合--all和--tags,只推分支和标签,正好是需要的部分。
5. 一次搬一批
项目多时,把对应关系写进一个文本文件,每行两列:GitLab 路径和 AngusGit 上的「所有者/仓库名」。AngusGit 上的空仓库要先按第 4 节第一步建好。
platform/backend/order-service platform/backend-order-service platform/frontend/order-web platform/frontend-order-web保存为repos.txt,然后执行:
whileread-rsrc dst;dogitclone--bare"https://gitlab.example.com/${src}.git"tmp.git||continuegit-Ctmp.git branch-mmaster main2>/dev/nullgit-Ctmp.git push"https://git.anguskit.com/${dst}.git"--allgit-Ctmp.git push"https://git.anguskit.com/${dst}.git"--tagsrm-rftmp.gitdone<repos.txt脚本逐行克隆、改名、推送,然后删掉本地副本。运行之前,先按开头手动搬一个仓库,让系统的凭据管理器记住 GitLab 和 AngusGit 两边的令牌;否则脚本每一行都会停下来问密码。
AngusGit 的批量导入也能一次处理很多地址,但它和单个导入一样只读公开项目、只带当前文件,而且导入的仓库全部是公开的。内网 GitLab 的项目,用上面的脚本更合适。
6. 验收:两边的分支和标签要一模一样
每个仓库推完,对比两边的分支和标签。下面的命令分别列出 GitLab 和 AngusGit 上所有分支、标签指向的提交,再逐行比较:
diff\<(gitls-remote--heads--tagshttps://gitlab.example.com/platform/backend/order-service.git|sort)\<(gitls-remote--heads--tagshttps://git.anguskit.com/platform/backend-order-service.git|sort)没有任何输出,说明两边一致。如果第 4 节把master改成了main,会看到这一对差异,属于预期;除此之外的差异,说明有分支或标签没推上去,重新执行一次推送即可。
最后打开 AngusGit 上的仓库,在分支页签核对数量,在提交记录里看作者和时间是否和 GitLab 一致。
上图左边是导入的结果,不是一次完整推送;推送验收要以git ls-remote没有意外差异为准。master改成main时,这一对名字对不上是预期的。
7. 哪些东西不在 Git 仓库里
推送只搬 Git 仓库里的内容。下面这些要在 AngusGit 上重新配置:
| GitLab 上的内容 | 是否随 git push 过去 | 在 AngusGit 上怎么处理 |
|---|---|---|
| 项目成员和角色 | 否 | 把成员加进 AngusGit 的团队,或在仓库设置 → 访问里加协作者 |
| 受保护分支 | 否 | 在仓库设置 → 分支保护里重新建规则 |
| 合并请求、议题、Wiki | 否 | 进行中的合并请求在 GitLab 上合并或关闭后再搬 |
.gitlab-ci.yml | 文件过去但不会运行 | 在控制台用导入 GitLab CI转成.anguscicd.yaml |
| Webhook | 否 | 在仓库设置 → Webhooks里重新添加 |
8. 出错时
| 你看到的 | 原因 | 怎么处理 |
|---|---|---|
| 导入时提示源仓库URL「…」无效或无法正常访问 | 项目是内部或私有的;填的是 SSH 地址;或者 AngusGit 服务器连不上 GitLab | 内部和私有项目按第 4 节推送。公开项目确认填的是 HTTPS 地址,并在 AngusGit 服务器上执行git ls-remote <地址>检查网络 |
克隆 GitLab 时HTTP Basic: Access denied | GitLab 开了双因素认证,或者密码不对 | 密码一栏改填 GitLab 个人访问令牌 |
推送时! [rejected] main -> main (fetch first) | AngusGit 上的仓库不是空的 | 删掉重建一个三项都不勾的空仓库 |
推送时repository '…' not found | AngusGit 上还没建这个仓库,或者所有者、仓库名和第 3 节的对应规则不一致 | 先建空仓库,再核对地址里的团队名和仓库名 |
| 验收时只有部分标签对不上 | 第二行--tags没执行,或者中途断开 | 重新执行一次git push <地址> --tags |
常见问题
GitLab 上的项目以后还会更新,能先搬一份,过段时间再补吗?
能。最简单的做法是再执行一遍第 4 节:重新git clone --bare,需要时改名,再推送。AngusGit 上已有的提交不会重复,推送只会把 GitLab 上新增的提交补过去。前提是这段时间里没有人直接往 AngusGit 推代码,否则两边分叉,推送会被拒绝。正式切换前反复同步、最后冻结 GitLab 再同步一次的做法,见 GitLab 迁移清单一文。
能保留 GitLab 合并请求里的评审记录吗?
不能。评审记录存在 GitLab 的数据库里,不在 Git 仓库中。需要留档时,在 GitLab 上导出或截图保存。
项目用了 Git LFS 怎么办?
AngusGit 不支持 Git LFS。推过去之后,LFS 管理的大文件只剩指针文件。这类文件要改成普通文件提交,或者放到制品库里。
GitLab 的子模块地址要改吗?
要。仓库里的.gitmodules如果写的是 GitLab 地址,子模块仍然会从 GitLab 拉。等子模块对应的仓库也搬到 AngusGit 之后,把.gitmodules里的地址改成 AngusGit 地址,再提交一次。
小结
从 GitLab 搬仓库,先看项目的可见性。公开项目可以直接用导入仓库,但只带当前文件;内部和私有项目,以及要保留历史的项目,在 AngusGit 建空仓库,git clone --bare之后用--all和--tags推送。子组路径提前定好对应规则,项目名里的点号提前改掉。一批项目用一个对应关系文件加循环脚本处理。每个仓库推完,用git ls-remote --heads --tags对比两边,一致才算搬完。
结论:GitLab 内部和私有仓库(以及需保留历史的仓库)应先将多层子组映射为「团队/仓库名」,再用
git clone --bare加git push --all/--tags推入空仓库,并用git ls-remote对比验收。
参考文章
- AngusGit 手册:仓库(新建、导入、批量导入)
- AngusGit 手册:组织与权限(团队、访问令牌)
- 导入 Git 仓库:填一个源地址,拿到默认分支的代码
- 从 GitLab 迁到 AngusGit:迁移清单、双跑和回滚
- HTTPS 克隆私有仓库:密码填访问令牌