Move a Gitee repository to an intranet Git host: code, permissions, and offline builds

# git# gitee# angusgit
Move a Gitee repository to an intranet Git host: code, permissions, and offline buildsWen Ping

This article explains how to move a Gitee repository onto an intranet AngusGit and keep building...

This article explains how to move a Gitee repository onto an intranet AngusGit and keep building after the public internet is disconnected. After reading it, you can choose import or git clone --bare plus a push according to whether the repository is public or private, grant Read, Write, or Admin again under Settings → Access, and place the runner image, the build image, and a dependency proxy on the intranet.

Sign in to AngusGit first. The push below uses SSH. If this machine has no ~/.ssh/id_ed25519.pub, run ssh-keygen -t ed25519 -C "you@example.com", press Enter for the path, and register the line from cat ~/.ssh/id_ed25519.pub that starts with ssh-ed25519 under Settings → Profile, on the SSH Keys tab, then click Add Key. Write the address as ssh://git@host:2222/owner/repo.git. The username is git. For HTTPS, open the Access Tokens tab, click Generate New Token, enter your current login password, select git:write, set the repository permission to WRITE, use your login name as the username, and use the token as the password. When you create the target repository, leave Add a README file, Add .gitignore, and Choose a license unchecked.

Built-in pipelines are available in AngusGit Team and Enterprise. If you only need code hosting, the first two parts apply on Community as well.

1. Sync the code: choose import or push

Import repository on AngusGit recognizes a Gitee URL. The form says "Supports GitHub, GitLab, Gitee, SourceForge, and more". Import has two limits. The source must be readable without signing in, which means a public repository. The result is the current files on the default branch, saved as one new commit on AngusGit. The old history, the other branches, and the tags stay behind.

Choose import or push from this table:

Repository on Gitee Method Result
Public, and you only need the latest code Import repository One new commit, no history
Public, and you need the history Clone, then push Full history, every branch, and every tag
Private Clone, then push Full history, every branch, and every tag

Teams that need the code to stay off the public internet usually keep Gitee repositories private, so they almost always clone and push.

  • Create an empty repository on AngusGit

Create a repository with the same name. Leave Add a README file, Add .gitignore, and Choose a license unchecked. Initial files make the histories differ, and the push is rejected.

  • Clone the whole repository from Gitee

Run this on a computer that can reach both Gitee and the intranet AngusGit. A private repository asks you to sign in to Gitee.

  • Rename the main branch when it is master

A new empty repository on AngusGit uses main as the default branch. Many older Gitee repositories use master. Rename first so the two sides line up.

  • Push every branch and tag

After the push, open the Branches tab and the commit history on the AngusGit repository and compare them with Gitee.

git clone --bare https://gitee.com/<org>/<repo>.git
cd <repo>.git
git branch -m master main
git push ssh://git@git.anguskit.com:2222/<owner>/<repo>.git --all
git push ssh://git@git.anguskit.com:2222/<owner>/<repo>.git --tags
Enter fullscreen mode Exit fullscreen mode

git clone --bare creates a bare repository: Git data only, with no working files to edit, which is what you want when you are forwarding the repository unchanged. The target must be a new empty repository. Do not push to anguskit/AngusKit, which already has content. Skip git branch -m when the main branch is already main. When a public repository only needs the current files, skip these commands and use Import repository. xlliu/hello-world-import is that import result: one branch and one commit.

The default SSH port on AngusGit is 2222, not 22, so the URL has the form ssh://git@host:2222/team/repo.git. The clone panel on the repository page also says "Non-22 ports use ssh://…:2222/… format". Copying from there is the safest.

After a trial move, and before the real cutover, Gitee may have new commits. Catch up once: tell the team to stop committing to Gitee, delete the local bare directory, and clone, rename, and push again with the commands above. Branches that nobody has committed to on AngusGit update to the latest. After the cutover, make the Gitee repository read-only or archive it.

2. Grant permissions again: look, write, and administer

Members and permissions on Gitee do not travel with the code. Grant them again on AngusGit. Skip a one-to-one copy of Gitee roles. Grant what each person actually does.

Open repository Settings, then Access on the left. There are two grants: Add collaborator for a person, or Authorize team for a team. The note lists five levels, low to high: Read, Triage, Write, Maintain, and Admin. The exact line is "Levels stack from low to high: Read < Triage < Write < Maintain < Admin. Multiple grants on the same repo take the highest." The three you will use most often:

What this person does Permission What it allows
Only view the code and clone Read Browse and clone; cannot triage Issues/PRs or push code
Write code, push branches, and open pull requests Write Push code; create and merge pull requests
Change repository settings, and manage branch protection and members Admin Full admin: delete/transfer, visibility, collaborators, and authorized teams

A pull request is a request to merge one branch into another after someone reviews the change. Someone who only files issues and tidies labels, and does not write code, can have Triage.

When there are many people, create teams by group under Settings → Team, add the people, then authorize the team on the repository. The button on the team page is New Team. Team Slug is the short name that appears in the repository URL. Later, when someone joins or leaves, you change the team membership and leave each repository alone.

The Access page of hello-world-import: Private is the current choice

This picture is Settings → Access for xlliu/hello-world-import. Visibility decides who can see the repository. Private is marked Current, and the description says "You choose who can see and commit to this repository." Public says "Anyone can see this repository. You choose who can commit." Under Add collaborator, the permission list is sitting on Write. The collaborator list says No collaborators. The team list says No authorized teams yet. When visibility is already private, you do not need to click Save visibility settings. Click Add collaborator when you are ready to add someone.

Two more settings on this page matter during a move.

  • Set the repository visibility to private. Turning on Make this repository private during a single import produces what you see now. If it was left off, choose Private on this page and click Save visibility settings. When it is already private, save is unnecessary.
  • Build machines fetch code with a deploy key. The next item on the left is Deploy Keys. The note says "Repository-scoped SSH public keys for CI/CD. Read-only keys can clone; write keys can push (branch protection still applies)." Add one when a build machine needs to fetch the code. It is not a required step of moving the repository.

3. How to build after the public internet is disconnected

Moving the code onto the intranet is the first step. Builds used to pull images from Docker Hub and download dependencies from the public Maven Central repository or the public npm registry. Those fetches fail as soon as the public internet is disconnected. Put everything the build needs on the intranet before you disconnect.

First, the runner itself. A runner is the program that actually runs pipeline jobs. Installed with Docker, the image is repo.anguskit.com/docker-public/angus-runner-agent:1.0.0. When the intranet cannot reach that address, pull and export it on a machine that can, then load it on the build machine or into an intranet image registry:

docker pull repo.anguskit.com/docker-public/angus-runner-agent:1.0.0
docker save -o angus-runner-agent.tar repo.anguskit.com/docker-public/angus-runner-agent:1.0.0
# After you copy the tar file to the build machine
docker load -i angus-runner-agent.tar
Enter fullscreen mode Exit fullscreen mode

Second, the build image. The image named in runner.image is pulled from that image address when the job runs. AngusGit has no setting that rewrites every image registry address for you, so you do two things: push the images you need to the intranet registry, then write the full intranet image name in the YAML.

docker pull repo.anguskit.com/docker-public/angus-ci-maven:21
docker tag repo.anguskit.com/docker-public/angus-ci-maven:21 registry.intra.example.com/ci/angus-ci-maven:21
docker push registry.intra.example.com/ci/angus-ci-maven:21
Enter fullscreen mode Exit fullscreen mode
    runner:
      mode: DOCKER
      image: registry.intra.example.com/ci/angus-ci-maven:21
      labels: ["linux", "docker"]
Enter fullscreen mode Exit fullscreen mode

Replace registry.intra.example.com with your intranet image registry.

Third, dependencies. For Maven, npm, and similar dependencies, run a dependency proxy on the intranet. One option is the artifact repository AngusRepo, proxying Maven Central and the npm registry. Point the project's settings.xml or .npmrc at that intranet proxy. The proxy caches from a place that can still reach the public internet. The build machine talks only to the intranet proxy.

Replace registry.intra.example.com with your own intranet image registry. After the images are inside the network and dependencies go through the proxy, disconnect the build machine from the public internet and start a pipeline.

When all three are ready, actually disconnect the build machine from the public internet and start a pipeline by hand. A successful run is what shows the offline build is complete. A common miss is a public download URL hardcoded in a build script, such as curl fetching a tool. Replace each of those with an intranet address.

4. Problems that show up during the move

What you see Cause What to do
Import of a private Gitee repository fails Import cannot sign in to the source Clone, then push
The push is rejected because the histories do not match The AngusGit repository was created with initial files checked Delete it, create an empty repository, and push again
After the push, the main branch is master and main is empty The branch was not renamed before the push Run git branch -m master main locally, push again, then delete the extra master branch on AngusGit
Connection refused The SSH URL omitted port 2222 Use an address in the form ssh://git@host:2222/...
The pipeline stalls while pulling an image, or reports that the image does not exist The YAML still names a public image Push the image to the intranet registry and write the full intranet image name in the YAML
Dependency downloads time out during the build The project still reaches a public dependency repository Configure the intranet dependency proxy and update settings.xml or .npmrc

Common questions

Can Gitee issues, pull requests, and Wiki move over too?

No. The move includes the Git repository itself. Recreate issues and Wiki by hand when you need them. Pull request discussions stay on Gitee, so keep the Gitee repository archived for a while in case you need to look something up.

Can AngusGit sync from Gitee on a schedule?

AngusGit has no repository mirror sync. During the move, the simple way to keep the two sides aligned is to let only one side accept writes. Before the cutover, everyone commits only to Gitee. At the cutover, clone and push once more as in section 1. After the cutover, everyone commits only to AngusGit. After the real cutover, you no longer need the sync.

Do developers have to clone their local repositories again?

No. In the local repository, run git remote set-url origin and point it at the AngusGit URL. Existing branches and commits stay where they are.

Summary

Moving a Gitee repository onto an intranet has three parts. Sync the code: use Import repository when a public repository only needs the latest code; use git clone --bare plus git push --all and git push --tags when the repository is private or you need the history, and rename a master main branch first. Grant permissions: under Settings → Access, give Read, Write, and Admin for look, write, and administer, grant by team, and give build machines a read-only deploy key. Build offline: load the runner image onto the intranet, push build images to the intranet registry and write the full address in the YAML, send dependencies through an intranet proxy, and then disconnect for real and run once. Built-in pipelines are available in Team and Enterprise. Community has no CI/CD menu. Use Team or Enterprise for the build section.

Conclusion: To move a private Gitee repository onto an intranet, keep the full history with git clone --bare plus git push --all and --tags, grant access again by team under Settings → Access, and point the runner image, the build image, and the dependency proxy at intranet addresses.

Further reading