由于項目需要,有時可能需要將代碼工程從一個gitlab服務器遷移至另一個gitlab服務器。下面介紹三種遷移的方式。
方案一:直接在gitlab界面上import
該方法是在gitlab網(wǎng)頁上一個一個代碼工程import, 針對代碼工程比較少的情況下適用。該方法是通過http的方式對舊服務器進行訪問的。
需要創(chuàng)建工程的組或子組(需先創(chuàng)建子組)下面,點擊“New project”,

擇“Import project”,看到如下界面,選擇“git Repo by URL”,

下面的界面填寫需要import的工程的url,http用戶名與密碼,和新的工程的名字,就可以開始”Create project”,

方案二:在服務器后臺拷貝代碼倉庫,執(zhí)行gitlab的import命令
該方法是直接在服務器后臺對代碼倉庫進行操作,適合有權限訪問新老服務器后臺,并且代碼工程比較多的情況下進行整體或批量遷移。
1. 在目的地服務器上創(chuàng)建一個臨時倉庫文件夾
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
則執(zhí)行import命令后,工程project3將遷移到新服務器的根目錄下面,group2將是新服務器上根目錄下的一個組,subgroup是group2下的一個子組,工程project2在subgroup下面。
如下圖所示:

方案三:將舊服務器上的工程克隆裸倉庫到本地,再將本地倉庫鏡像推送到新服務器
該方法適合遷移工程量較大,但無法在服務器后臺進行操作的情況下使用。該方法對新舊服務器可以通過ssh進行訪問。
1. 獲取舊服務器上代碼工程的地址,克隆工程的裸倉庫到本地
git clone –bare git@old_url:root/project3.git
2. 在新服務器上創(chuàng)建新的空工程
eg:新創(chuàng)建的空工程地址是:git@destination_url:root/project3.git
3. 推送本地裸倉庫鏡像到新服務器
git push –mirror git@destination_url:root/project3.git
對于該方案,在需要遷移的代碼工程量比較少的情況,可以從gitlab界面上逐個復制出舊倉庫的所有工程路徑,以及在新服務器上逐個創(chuàng)建新工程。但是對于代碼工程較多的情況,逐一列出工程和創(chuàng)建工程就比較耗時了。gitlab的web界面沒有提供一次性列出所有工程,以及一次性創(chuàng)建多個工程的選項,但是提供了對應的API進行訪問獲取。
在調用API前,需要先在gitlab上面創(chuàng)建Access Token

下面是如何通過API獲取舊服務器上所有工程以及在新服務器上批量創(chuàng)建新工程的腳本。
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. 在新服務器上批量創(chuàng)建工程:
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
###列出需要創(chuàng)建的空代碼工程名稱。如果工程量太大,可將代碼工程名稱放在一個文件里面,然后從文件中讀取。
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 是希望創(chuàng)建的新工程所在的組的Group ID,可以從組的信息中得到:

如果調用接口時沒有傳遞namespace_id,則新工程默認創(chuàng)建在用戶的根目錄下面。
3. 克隆舊服務器上的代碼工程到本地,在新服務器上創(chuàng)建空工程,將舊代碼工程推送到新服務器
基于前兩步已經(jīng)得到了舊服務器上需要遷移的所有代碼工程地址,以及新服務器上新的空代碼工程地址,通過腳本執(zhí)行推送:
import os
##舊服務器上需要遷移的工程路徑列表,以及對應的新服務器上創(chuàng)建的空工程的路徑列表。
##如果工程量很大,可將該內容放入文件中,從文件中讀取
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)
所有工程便遷移完成。
總結
上面幾種方式各有不同的適用場景,可根據(jù)需要遷移的項目實際情況進行選擇。