Gitlab代码工程迁移
由于项目需要,有时可能需要将代码工程从一个gitlab服务器迁移至另一个gitlab服务器。下面介绍三种迁移的方式。
方案一:直接在gitlab界面上import
该方法是在gitlab网页上一个一个代码工程import, 针对代码工程比较少的情况下适用。该方法是通过http的方式对旧服务器进行访问的。
需要创建工程的组或子组(需先创建子组)下面,点击“New project”,

择“Import project”,看到如下界面,选择“git Repo by URL”,

下面的界面填写需要import的工程的url,http用户名与密码,和新的工程的名字,就可以开始”Create project”,

方案二:在服务器后台拷贝代码仓库,执行gitlab的import命令
该方法是直接在服务器后台对代码仓库进行操作,适合有权限访问新老服务器后台,并且代码工程比较多的情况下进行整体或批量迁移。
1. 在目的地服务器上创建一个临时仓库文件夹
eg: /var/opt/gitlab/git-data/repositories-import
2. 将旧服务器上仓库内的所有内容拷贝到目的地服务器上的临时仓库文件夹
旧服务器仓库默认路径是 /var/opt/gitlab/git-data/repositories
3. 设置目录权限
chown -R git.git /var/opt/gitlab/git-data/ repositories-import
4. 开始迁移
gitlab-rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import/']
注意事项:
- 如需整体迁移,则将旧仓库整体内容拷贝; 如只需迁移部分工程,可只拷贝旧仓库中对应的工程
- 代码仓库目录repository-import下面的层级结构将对应迁移过后的工程的层级结构
eg: 如果repository-import下面的层级结构是- project3.git,
- group1/project1.git,
- group2/subgroup/project2.git
则执行import命令后,工程project3将迁移到新服务器的根目录下面,group2将是新服务器上根目录下的一个组,subgroup是group2下的一个子组,工程project2在subgroup下面。
如下图所示:

方案三:将旧服务器上的工程克隆裸仓库到本地,再将本地仓库镜像推送到新服务器
该方法适合迁移工程量较大,但无法在服务器后台进行操作的情况下使用。该方法对新旧服务器可以通过ssh进行访问。
1. 获取旧服务器上代码工程的地址,克隆工程的裸仓库到本地
git clone –bare git@old_url:root/project3.git
2. 在新服务器上创建新的空工程
eg:新创建的空工程地址是:git@destination_url:root/project3.git
3. 推送本地裸仓库镜像到新服务器
git push –mirror git@destination_url:root/project3.git
对于该方案,在需要迁移的代码工程量比较少的情况,可以从gitlab界面上逐个复制出旧仓库的所有工程路径,以及在新服务器上逐个创建新工程。但是对于代码工程较多的情况,逐一列出工程和创建工程就比较耗时了。gitlab的web界面没有提供一次性列出所有工程,以及一次性创建多个工程的选项,但是提供了对应的API进行访问获取。
在调用API前,需要先在gitlab上面创建Access Token

下面是如何通过API获取旧服务器上所有工程以及在新服务器上批量创建新工程的脚本。
1. 获取服务器上所有的工程地址:
from urllib.request import urlopen import json import time import os gitlabAddress = 'xxx.xxx.xxx.xxx' ###gitlab address gitlabAccessToken = 'cTm1Sr5pJ1FxyS******' ###your Access Tokens projectURL_fd = open("allProjectURL.txt",'w') for index in range(10): url = "http://%s/api/v4/projects?private_token=%s&per_page=100&page=%d&order_by=name&simple=true" % (gitlabAddress, gitlabAccessToken, index+1) print('\n' + url) allProjects = urlopen(url) allProjectsDict = json.loads(allProjects.read().decode()) if len(allProjectsDict) == 0: break for eachProject in allProjectsDict: ProjectURL = eachProject['ssh_url_to_repo'] projectURL_fd.writelines(ProjectURL+ '\n') print(ProjectURL) time.sleep(1) projectURL_fd.close()
2. 在新服务器上批量创建工程:
import subprocess import json import time ###gitlabAddress in which you want to create new projects gitlabAddress = 'xxx.xxx.xxx.xxx' ###your access token in gitlab which you want to create new projects private_token = 'cTm1Sr5pJ1FxySF*****' ###change the group_id which can see in gitlab group info namespace_id = 16 ###列出需要创建的空代码工程名称。如果工程量太大,可将代码工程名称放在一个文件里面,然后从文件中读取。 needToCreatedProjects=( 'project1', 'project2', 'project3', 'project4', 'project5' ) for eachProject in needToCreatedProjects: p = subprocess.Popen('curl --request POST --header "PRIVATE-TOKEN: %s" --data "name=%s&namespace_id=%d" http://%s/api/v4/projects'%(private_token,eachProject,namespace_id, gitlabAddress),stdout=subprocess.PIPE,stderr=subprocess.PIPE,) p.wait() ####print the repo url which new created if p.poll() == 0: result_dic = json.loads(p.stdout.read().decode()) print (result_dic['ssh_url_to_repo']) time.sleep(1)
namespace_id 是希望创建的新工程所在的组的Group ID,可以从组的信息中得到:

如果调用接口时没有传递namespace_id,则新工程默认创建在用户的根目录下面。
3. 克隆旧服务器上的代码工程到本地,在新服务器上创建空工程,将旧代码工程推送到新服务器
基于前两步已经得到了旧服务器上需要迁移的所有代码工程地址,以及新服务器上新的空代码工程地址,通过脚本执行推送:
import os ##旧服务器上需要迁移的工程路径列表,以及对应的新服务器上创建的空工程的路径列表。 ##如果工程量很大,可将该内容放入文件中,从文件中读取 project_list = ( ## old project url which got in step1 ## new project url which created in step2 ('git@old_url:group2/subgroup/project1.git' , 'git@new_url:group2/subgroup/project1.git' ), ('git@old_url:group2/subgroup/project2.git' , 'git@new_url:group2/subgroup/project2.git' ), ('git@old_url:group2/subgroup/project3.git' , 'git@new_url:group2/subgroup/project3.git' ), ('git@old_url:group2/subgroup/project4.git' , 'git@new_url:group2/subgroup/project4.git' ), ('git@old_url:group2/subgroup/project5.git' , 'git@new_url:group2/subgroup/project5.git' ) ) ##root path of the local repositories which cloned to root_path = os.getcwd() print (root_path) for item in project_list: old_projectURL = item[0] new_projectURL = item[1] print (old_projectURL, new_projectURL) ##clone old projects to local os.chdir(root_path) clone_cmd = 'git clone --bare ' + old_projectURL.strip() os.system(clone_cmd) ### push local projects to remote old_projectName = old_projectURL.split('/')[-1] os.chdir(os.path.join(root_path,old_projectName)) push_cmd = 'git push --mirror ' + new_projectURL.strip() os.system(push_cmd)
所有工程便迁移完成。
总结
上面几种方式各有不同的适用场景,可根据需要迁移的项目实际情况进行选择。