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)
所有工程便遷移完成。
總結
上面幾種方式各有不同的適用場景,可根據需要遷移的項目實際情況進行選擇。