该方案旨在实现在不同的 Git 代码托管平台( Gerrit 和 GitLab)之间的代码迁移和同步。
一、部署Gerrit
切换root用户
sudo su
新建gerrit用户
sudo adduser gerrit # 创建gerrit用户
sudo usermod -aG sudo gerrit # 赋予sudo管理权限
su gerrit # 切换到gerrit用户
OpenJdk8
sudo apt install -y openjdk-8-jdk
Nginx
sudo apt install -y nginx
apache2-utils
apt udapte
sudo apt install -y apache2-utils
Gerrit
mkdir ~/gerrit_server
cd gerrit_server
wget https://gerrit-releases.storage.googleapis.com/gerrit-3.0.0.war
java -jar gerrit*.war init -d review_site
Nginx代理
cat /etc/nginx/nginx.conf
events {
# 定义事件处理参数,如 worker_connections
worker_connections 1024;
}
http {
# 设置日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 设置访问日志路径和格式
access_log /var/log/nginx/access.log main;
# 设置错误日志路径
error_log /var/log/nginx/error.log error;
# 设置默认服务器
server {
listen 80 default_server;
listen [::]:80 default_server;
# 设置默认服务器的根目录
root /var/www/html;
# 设置默认服务器的主页
index index.html index.htm index.nginx-debian.html;
# 处理默认服务器的请求
location / {
try_files $uri $uri/ =404;
}
}
# 设置访问代理
server {
# 设置访问代理端口
listen *:8443;
server_name localhost;
location / {
auth_basic "Welcome to Gerrit Code Review Site";
auth_basic_user_file /home/gerrit/gerrit_server/review_site/etc/passwd;
proxy_pass http://localhost:8081;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
location /login/ {
proxy_pass http://localhost:8081;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
}
报错记录:
查看报错日志
sudo cat /var/log/nginx/error.log
2024/04/29 15:09:41 [crit] 68075#68075: *48 open() "/home/gerrit/gerrit_server/review_site/etc/passwd" failed (13: Permission denied), client: 59.33.175.234, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "106.53.*.*:8443", referrer: "http://106.53.*.*:8443/"
此时访问报错500 原因是nginx进程用户是nobody,但是/home/gerrit/gerrit_server/review_site/etc/passwd是gerrit权限:
解决方法:
sudo chmod o+r /home/gerrit/gerrit_server/review_site/etc/passwd
sudo nginx -s reload
再次访问正常。
二、部署Gitlab
sudo su
sudo apt install -y curl openssh-server ca-certificates postfix
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo EXTERNAL_URL="http://gitlab.linuxtechi.net" apt install gitlab-ce
sudo dpkg -i gitlab-ce_15.10.0-ce.0_amd64.deb
cat /etc/gitlab/gitlab.rb
external_url 'http://106.53.*.*'
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart
- 用户名:root
- 密码:从 /etc/gitlab/initial_root_password 获取密码
**************************************=
三、权限配置
ssh-keygen -m PEM -t rsa -C "wzk@test.com" 注意要使用PEM
gerrit--->gitlab
ssh-copy-id ubuntu@106.53.*.*
gitlab--->gerrit
ssh-copy-id gerrit@106.53.*.*
设置gerrit同步gitlab的配置文件(配置gitlab服务器的访问权限)
vi ~/.ssh/config
HOST 106.53.*.*
User ubuntu
Port 22
IdentityFile ~/.ssh/id_rsa
PreferredAuthentications publickey
PubkeyAcceptedKeyTypes +ssh-rsa
HOST 106.53.*.*
User gerrit
PubkeyAcceptedKeyTypes +ssh-rsa
IdentityFile ~/.ssh/id_rsa
Port 29418
三、replication插件配置
- 在gerrit的git仓库目录内删除wangzk-test仓库
sudo rm -rf wangzk-test.git
- 下载gitlab的wangzk-test仓库,需要指定–bare进行独立拉取以便脱离远程分支
git clone --bare ssh://git@106.53.*.*/root/wangzk-test.git
- 自动同步项目配置
vim ~/gerrit_server/review_site/etc/replication.config
[remote "wangzk-test"]
rescheduleDelay = 15
projects = wangzk-test
url = ssh://git@106.53.*.*/root/wangzk-test.git
push = +refs/heads/*:refs/heads/*
push = +refs/tags/*:refs/tags/*
push = +refs/changes/*:refs/changes/*
threads = 3
保存退出, 并重启
~/gerrit_server/review_site/bin/gerrit.sh restart
五、gerrit拉取并修改同步项目
git clone "ssh://gerrit@106.53.*.*:29418/wangzk-test" && scp -p -P 29418 gerrit@106.53.*.*:hooks/commit-msg "wangzk-test/.git/hooks/"
报错记录:
报错:
[sudo] password for gerrit:
Cloning into 'wangzk-test'...
gerrit@106.53.*.*: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
原因:在Gerrit服务器的OpenSSH的版本号,如果版本≥8.8,就会出现这个问题,终端执行ssh -V查看,发现版本号≥8.8,就需要如下操作:
cat ~/.ssh/config
HOST 106.53.*.*
User ubuntu #gitlab服务器用户名
Port 22 # gitlab 访问端口, 如果默认22 将不用添加该项
IdentityFile /home/ubuntu/.ssh/id_rsa # 秘钥在服务器的路径
PreferredAuthentications publickey # 首选认证方式
HOST 106.53.*.*
User gerrit
PubkeyAcceptedKeyTypes +ssh-rsa
IdentityFile ~/.ssh/id_rsa
Port 29418
再重新拉取,就可以拉取成功了。
报错:cat ~/gerrit_server/review_site/logs/replication_log
[2024-04-30 11:56:52,166] [74c4c4b0] Replication to ssh://git@106.53.*.*/root/wangzk-test.git started...
[2024-04-30 11:56:52,166] [74c4c4b0] Push to ssh://git@106.53.*.*/root/wangzk-test.git references: [RemoteRefUpdate[remoteName=refs/heads/main, NOT_ATTEMPTED, (null)...5abe0ff4e36883fc6be6531479c423daa4de2461, srcRef=refs/heads/main, forceUpdate, message=null]]
[2024-04-30 11:56:52,167] [74c4c4b0] Cannot replicate to ssh://git@106.53.*.*/root/wangzk-test.git
org.eclipse.jgit.errors.TransportException: ssh://git@106.53.*.*/root/wangzk-test.git: java.io.FileNotFoundException: /home/ubuntu/.ssh/id_rsa # 秘钥在服务器的路径 (Permission denied)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:191)
at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:140)
at org.eclipse.jgit.transport.TransportGitSsh$SshPushConnection.<init>(TransportGitSsh.java:339)
at org.eclipse.jgit.transport.TransportGitSsh.openPush(TransportGitSsh.java:176)
at org.eclipse.jgit.transport.PushProcess.execute(PushProcess.java:160)
at org.eclipse.jgit.transport.Transport.push(Transport.java:1346)
at org.eclipse.jgit.transport.Transport.push(Transport.java:1392)
at com.googlesource.gerrit.plugins.replication.PushOne.pushVia(PushOne.java:462)
at com.googlesource.gerrit.plugins.replication.PushOne.runImpl(PushOne.java:432)
at com.googlesource.gerrit.plugins.replication.PushOne.runPushOperation(PushOne.java:316)
at com.googlesource.gerrit.plugins.replication.PushOne.lambda$run$0(PushOne.java:282)
at com.google.gerrit.server.util.RequestScopePropagator.lambda$cleanup$1(RequestScopePropagator.java:182)
at com.google.gerrit.server.util.RequestScopePropagator.lambda$context$0(RequestScopePropagator.java:170)
at com.google.gerrit.server.git.PerThreadRequestScope$Propagator.lambda$scope$0(PerThreadRequestScope.java:70)
at com.googlesource.gerrit.plugins.replication.PushOne.run(PushOne.java:285)
at com.google.gerrit.server.logging.LoggingContextAwareRunnable.run(LoggingContextAwareRunnable.java:72)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at com.google.gerrit.server.git.WorkQueue$Task.run(WorkQueue.java:610)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
Caused by: com.jcraft.jsch.JSchException: java.io.FileNotFoundException: /home/ubuntu/.ssh/id_rsa # 秘钥在服务器的路径 (Permission denied)
at com.jcraft.jsch.KeyPair.load(KeyPair.java:543)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:407)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:367)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.java:399)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:335)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:208)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:138)
... 23 more
Caused by: java.io.FileNotFoundException: /home/ubuntu/.ssh/id_rsa # 秘钥在服务器的路径 (Permission denied)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at com.jcraft.jsch.Util.fromFile(Util.java:508)
at com.jcraft.jsch.KeyPair.load(KeyPair.java:540)
... 30 more
解决方法:
gerrit@VM-12-16-ubuntu:/home/ubuntu$ cat ~/.ssh/config
HOST 106.53.*.*
User ubuntu #gitlab服务器用户名
Port 22
IdentityFile ~/.ssh/id_rsa
PreferredAuthentications publickey
PubkeyAcceptedKeyTypes +ssh-rsa
HOST 106.53.*.*
User gerrit
PubkeyAcceptedKeyTypes +ssh-rsa
IdentityFile ~/.ssh/id_rsa
Port 29418
查看已加载的插件配置
ssh -p 29418 106.53.*.* gerrit plugin ls
Name Version Status File
-------------------------------------------------------------------------------
codemirror-editor v3.0.0 ENABLED codemirror-editor.jar
commit-message-length-validator v3.0.0 ENABLED commit-message-length-validator.jar
delete-project v3.0.0 ENABLED delete-project.jar
download-commands v3.0.0 ENABLED download-commands.jar
gitiles v3.0.0 ENABLED gitiles.jar
hooks v3.0.0 ENABLED hooks.jar
plugin-manager v3.0.0 ENABLED plugin-manager.jar
replication v3.0.0 ENABLED replication.jar
reviewnotes v3.0.0 ENABLED reviewnotes.jar
singleusergroup v3.0.0 ENABLED singleusergroup.jar
webhooks v3.0.0 ENABLED webhooks.jar
报错:[2024-04-30 13:54:53,279] [ab022398] Replication to ssh://git@106.53.*.*/root/wangzk-test.git started...
[2024-04-30 13:54:53,280] [ab022398] Push to ssh://git@106.53.*.*/root/wangzk-test.git references: [RemoteRefUpdate[remoteName=refs/heads/main, NOT_ATTEMPTED, (null)...5abe0ff4e36883fc6be6531479c423daa4de2461, srcRef=refs/heads/main, forceUpdate, message=null]]
[2024-04-30 13:54:53,284] [ab022398] Cannot replicate to ssh://git@106.53.*.*/root/wangzk-test.git
org.eclipse.jgit.errors.TransportException: ssh://git@106.53.*.*/root/wangzk-test.git: invalid privatekey: [B@61d70fa2
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:191)
at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:140)
at org.eclipse.jgit.transport.TransportGitSsh$SshPushConnection.<init>(TransportGitSsh.java:339)
at org.eclipse.jgit.transport.TransportGitSsh.openPush(TransportGitSsh.java:176)
at org.eclipse.jgit.transport.PushProcess.execute(PushProcess.java:160)
at org.eclipse.jgit.transport.Transport.push(Transport.java:1346)
at org.eclipse.jgit.transport.Transport.push(Transport.java:1392)
at com.googlesource.gerrit.plugins.replication.PushOne.pushVia(PushOne.java:462)
at com.googlesource.gerrit.plugins.replication.PushOne.runImpl(PushOne.java:432)
at com.googlesource.gerrit.plugins.replication.PushOne.runPushOperation(PushOne.java:316)
at com.googlesource.gerrit.plugins.replication.PushOne.lambda$run$0(PushOne.java:282)
at com.google.gerrit.server.util.RequestScopePropagator.lambda$cleanup$1(RequestScopePropagator.java:182)
at com.google.gerrit.server.util.RequestScopePropagator.lambda$context$0(RequestScopePropagator.java:170)
at com.google.gerrit.server.git.PerThreadRequestScope$Propagator.lambda$scope$0(PerThreadRequestScope.java:70)
at com.googlesource.gerrit.plugins.replication.PushOne.run(PushOne.java:285)
at com.google.gerrit.server.logging.LoggingContextAwareRunnable.run(LoggingContextAwareRunnable.java:83)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at com.google.gerrit.server.git.WorkQueue$Task.run(WorkQueue.java:610)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@61d70fa2
at com.jcraft.jsch.KeyPair.load(KeyPair.java:664)
at com.jcraft.jsch.KeyPair.load(KeyPair.java:561)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:407)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:367)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.java:399)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:335)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:208)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:138)
... 23 more
解决方法:
原因是生成密钥的时候使用openssh版本生成导致版本过高:
ssh-keygen -m PEM -t rsa 重新生成旧格式的key
再次重新加载配置
~/gerrit_server/review_site/bin/gerrit.sh restart
推送成功
[2024-04-30 14:06:55,545] [ab022398] Replication to ssh://git@106.53.*.*/root/wangzk-test.git started...
[2024-04-30 14:06:55,546] [ab022398] Push to ssh://git@106.53.*.*/root/wangzk-test.git references: [RemoteRefUpdate[remoteName=refs/heads/main, NOT_ATTEMPTED, (null)...5abe0ff4e36883fc6be6531479c423daa4de2461, srcRef=refs/heads/main, forceUpdate, message=null]]
[2024-04-30 14:07:00,034] [ab022398] Replication to ssh://git@106.53.*.*/root/wangzk-test.git completed in 4489ms, 857340ms delay, 14 retries
查看gitlab仓库,发现推送到gerrit的信息同步到了gitlab上:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/78a721a23b44490ba7612e666b233e00.png
四、测试:将gerrit已存在的项目同步到gitlab的空项目(同名项目已创建)
不可以将已存在的代码仓库直接replication同步到gitlab,需要如下操作步骤:
将 Gerrit 中的所有代码、分支和提交信息复制到 GitLab:
- 在 GitLab 中创建新项目:首先,在 GitLab 中创建一个新项目,以便将 Gerrit 中的代码复制过去。在 GitLab 的界面上,点击 “New Project” 或者 “New Repository”.
- 克隆 Gerrit 仓库:使用 Git 命令克隆 Gerrit 仓库到本地:
git clone --mirror "ssh://gerrit@106.53.*.*:29418/test0506" && scp -p -P 29418 gerrit@106.53.*.*2:hooks/commit-msg "test0506/.git/hooks/"
–mirror 是 Git 中用于克隆镜像仓库的选项。克隆镜像仓库时,会复制源仓库的所有引用(包括分支、标签等),并将它们作为裸仓库(bare repository)保存在本地。裸仓库不包含工作目录,只包含 Git 版本控制所需的文件。这意味着你不能在镜像仓库中进行常规的开发工作,但可以用于克隆和同步远程仓库的完整副本。
使用 --mirror 选项克隆镜像仓库的主要优点是它可以保持源仓库的完整性和一致性,包括所有的分支、标签和提交历史。这样,在需要备份或者迁移仓库时,镜像仓库可以提供一个完整的副本,确保不丢失任何数据。
具体来说,–mirror 选项会做以下几件事情:
- 复制所有引用:包括分支、标签和其他引用。
- 不创建工作目录:裸仓库不包含工作目录,只包含 Git 版本控制所需的文件。
- 保持完整性:保持源仓库的完整性和一致性,包括所有的分支、标签和提交历史。
添加 GitLab 作为远程仓库:进入到克隆下来的 Gerrit 仓库目录中,然后将 GitLab 仓库添加为远程仓库:
cd test0506.git
git remote add gitlab ssh://git@106.53.*.*:/root/test0506.git
推送代码、分支和提交信息到 GitLab:将本地仓库中的所有内容(包括所有分支、提交等)推送到 GitLab 仓库:
git push gitlab --all
推送标签:
git push gitlab --tags
开始gerrit与gitlab同步:
cd /home/gerrit/gerrit_server/review_site/git
ls -l
total 24
drwxrwxr-x+ 7 gerrit gerrit 4096 Apr 29 13:41 All-Projects.git
drwxrwxr-x+ 7 gerrit gerrit 4096 Apr 29 15:14 All-Users.git
drwxrwxr-x 7 gerrit gerrit 4096 Apr 29 15:23 test0429.git
drwxrwxr-x 7 gerrit gerrit 4096 May 6 16:20 test0506.git
drwxrwxr-x 7 gerrit gerrit 4096 Apr 30 14:53 test-two.git
drwxrwxr-x 8 gerrit gerrit 4096 May 6 16:02 wangzk-test.git
sudo rm -rf test0506.git
git clone --bare ssh://git@106.53.*.*/root/test0506.git
vim ~/gerrit_server/review_site/etc/replication.config
[remote "test0506"]
rescheduleDelay = 15
projects = test0506
url = ssh://git@106.53.*.*:/root/test0506.git
push = +refs/heads/*:refs/heads/*
push = +refs/tags/*:refs/tags/*
重新加载replication配置:
~/gerrit_server/review_site/bin/gerrit.sh restart
上传文件到gerrit,观察gitlab:
git clone "ssh://gerrit@106.53.*.*:29418/test0506" && scp -p -P 29418 gerrit@106.53*.*:hooks/commit-msg "test0506/.git/hooks/"
Cloning into 'test0506'...
remote: Counting objects: 11, done
remote: Finding sources: 100% (11/11)
remote: Total 11 (delta 0), reused 11 (delta 0)
Receiving objects: 100% (11/11), done.
commit-msg 100% 1790 712.2KB/s 00:00
gerrit@VM-12-16-ubuntu:~/test$ ls
test0506 test-two wangzk-test
gerrit@VM-12-16-ubuntu:~/test$ cd test0506/
gerrit@VM-12-16-ubuntu:~/test/test0506$ ls
README.md
gerrit@VM-12-16-ubuntu:~/test/test0506$ git branch
* main
gerrit@VM-12-16-ubuntu:~/test/test0506$ git checkout master
Branch 'master' set up to track remote branch 'master' from 'origin'.
Switched to a new branch 'master'
gerrit@VM-12-16-ubuntu:~/test/test0506$ git branch
main
* master
gerrit@VM-12-16-ubuntu:~/test/test0506$ ls
11111.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ vim 2222.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ ls
11111.txt 2222.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ git add .
gerrit@VM-12-16-ubuntu:~/test/test0506$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: 2222.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ git commit -m'[2222.txt][upgrade][xxxxx][No ID][NA]'
[master 35ca15c] [2222.txt][upgrade][xxxxx][No ID][NA]
1 file changed, 1 insertion(+)
create mode 100644 2222.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ git push origin master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 324 bytes | 324.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Processing changes: refs: 1, done
To ssh://106.53.*.*:29418/test0506
c51dee1..35ca15c master -> master
gerrit@VM-12-16-ubuntu:~/test/test0506$
同步成功。