Proses migrasi seringkali merupakan tugas yang sulit, terutama ketika jumlah informasi yang perlu ditransfer begitu besar sehingga menjadi lebih menguntungkan untuk mengotomatiskannya. Adalah kebutuhan untuk bermigrasi dari Gitolite ke GitLab yang mendorong saya untuk menulis artikel tentang pengalaman saya dalam masalah ini.

Untuk memigrasi repositori, saya akan menggunakan komputer dengan sistem operasi CentOS 7. Di atasnya, saya perlu menginstal set aplikasi berikut: git, ssh-agent, curl, jq, xargs .
Untuk memulai, kita perlu mendapatkan kunci akses ke API GitLab. Di antarmuka web, buka bagian pengaturan pengguna. Selanjutnya, pilih item menu “Token Akses” . Dalam formulir yang terbuka, Anda harus menentukan nama kunci yang diterima, dan Anda juga dapat menentukan periode kapan kunci akan aktif. Di bawah, centang kotak di sebelah item api dan klik tombol "Buat token akses pribadi" . Kunci ini akan digunakan saat mengirim permintaan ke API GitLab.
- Mempersiapkan lingkungan kerja
 - GitLab SSH, , GitLab. GitLab «Admin area» «Deploy keys» «New deploy key». , . , GitLab. bash: 
 - curl -k -X GET --header "PRIVATE-TOKEN: <your private token>" <gitlab url>/api/v4/deploy_keys
 
 - : SSH git , ssh-agent. : 
 - eval `ssh-agent`
 
 - ssh-add ~/.ssh/id_rsa
 
 
- GitLab API
 - GitLab, POST API GitLab, , . Projects API GitLab GitLab. 
 - 
initRemoteRepository() {
    local response=`curl -s -k -X POST --header "Private-Token: $2" --data "name=$3&namespace_id=$4&visibility=private&description=$3" $1/api/v4/projects`
    local id=`echo $response | jq -r ".id"`
    echo "$id"
}
 
 - initRemoteRepository . .
 : –k , GitLab .
 
 
- API
 - , , . Deploy Keys API GitLab GitLab. 
 - 
enableRepositoryDeployKey() {
    local response=`curl -s -k -X POST --header "Private-Token: $2" $1/api/v4/projects/$3/deploy_keys/$4/enable`
    echo "$response"
}
 
 - enableRepositoryDeployKey . 
 - 
setRepositoryWriteAccess() {
    local response=`curl -s -k -X PUT --header "PRIVATE-TOKEN: $2" --header "Content-Type: application/json" --data '{"can_push": true}' $1/api/v4/projects/$3/deploy_keys/$4`
    echo "$response"
}
 
 - setRepositoryWriteAccess . 
 
 - , . GitLab, . . GitLab. 
 - 
getCanonicalBranchName() {
    local branch=""
    IFS=$2 read -r -a array <<< "$1"
    length=${#array[@]}
    for index in "${!array[@]}"
    do
        if [ $index -gt 0 ]; then
            if [ $index -eq 1 ]; then
                local branch="${array[index]}"
            else
                local branch="$branch/${array[index]}"
            fi
        fi
    done
    echo "$branch"
}
PSWD="$(dirname "$0")"
cd $PSWD
while IFS= read -r REPOSITORY
do
    echo "====================  <$REPOSITORY>  ===================="
    GITOLITE_REPO=$GITOLITE$REPOSITORY
    echo "Run cloning remote repository $GITOLITE_REPO"
    git clone $GITOLITE_REPO
    cd $REPOSITORY
    GITLAB_REPO=$GITLAB$REPOSITORY.git
    echo "Initialize remote gitgab repository $GITLAB_REPO"
    PROJECT=$(initRemoteRepository $GITLAB_URL $API_TOKEN $REPOSITORY)
    echo "Remote repository initialized identifier $PROJECT"
    echo "Add deploy key and enable write access to remote repository $REPOSITORY ($PROJECT)"
    response=$(enableRepositoryDeployKey $GITLAB_URL $API_TOKEN $PROJECT $DEPLOY_KEY_ID)
    response =$(setRepositoryWriteAccess $GITLAB_URL $API_TOKEN $PROJECT $DEPLOY_KEY_ID)
    echo "Add new remote url for repository $GITLAB_REPO"
    git remote add gitlab $GITLAB_REPO
    
    IFS_BACK=$IFS
    IFS=$'\n'
    branches=$(git branch -r)
    for branchName in $branches; do
        trimBranchName=`echo $branchName | xargs`
        canonicalBranchName=$(getCanonicalBranchName $trimBranchName '/')
        echo "$trimBranchName ($canonicalBranchName) init push"
        git checkout -b $canonicalBranchName remotes/origin/$canonicalBranchName
        git push -f gitlab $canonicalBranchName
    done
    IFS=$IFS_BACK
    cd ..
    rm -r -f $REPOSITORY
    echo "====================  <$REPOSITORY>  ===================="
    echo ""
done < "$REPOSITORIES"
 
 - , . . 
 
Skrip lengkapREPOSITORIES="<repositories_file>"
GITOLITE="<gitolite_ssh_url>"
GITLAB_URL="<gitlab_api_url>"
GITLAB="<gitolite_ssh_url>"
API_TOKEN="<api_access_token>"
DEPLOY_KEY_ID="<deploy_key_identifier>"
initRemoteRepository() {
        local response=`curl -s -k -X POST --header "Private-Token: $2" --data "name=$3&namespace_id=$4&visibility=private&description=$3" $1/api/v4/projects`
        local id=`echo $response | jq -r ".id"`
        echo "$id"
}
setRepositoryWriteAccess() {
    local response=`curl -s -k -X PUT --header "PRIVATE-TOKEN: $2" --header "Content-Type: application/json" --data '{"can_push": true}' $1/api/v4/projects/$3/deploy_keys/$4`
    echo "$response"
}
enableRepositoryDeployKey() {
    local response=`curl -s -k -X POST --header "Private-Token: $2" $1/api/v4/projects/$3/deploy_keys/$4/enable`
    echo "$response"
}
getCanonicalBranchName() {
    local branch=""
    IFS=$2 read -r -a array <<< "$1"
    length=${#array[@]}
    for index in "${!array[@]}"
    do
        if [ $index -gt 0 ]; then
            if [ $index -eq 1 ]; then
                local branch="${array[index]}"
            else
                local branch="$branch/${array[index]}"
            fi
        fi
    done
    echo "$branch"
}
PSWD="$(dirname "$0")"
cd $PSWD
while IFS= read -r REPOSITORY
do
    echo "====================  <$REPOSITORY>  ===================="
    GITOLITE_REPO=$GITOLITE$REPOSITORY
    echo "Run cloning remote repository $GITOLITE_REPO"
    git clone $GITOLITE_REPO
    cd $REPOSITORY
    GITLAB_REPO=$GITLAB$REPOSITORY.git
    echo "Initialize remote gitgab repository $GITLAB_REPO"
    PROJECT=$(initRemoteRepository $GITLAB_URL $API_TOKEN $REPOSITORY)
    echo "Remote repository initialized identifier $PROJECT"
    echo "Add deploy key and enable write access to remote repository $REPOSITORY ($PROJECT)"
    response=$(enableRepositoryDeployKey $GITLAB_URL $API_TOKEN $PROJECT $DEPLOY_KEY_ID)
    response=$(setRepositoryWriteAccess $GITLAB_URL $API_TOKEN $PROJECT $DEPLOY_KEY_ID)
    echo "Add new remote url for repository $GITLAB_REPO"
    git remote add gitlab $GITLAB_REPO
    
    IFS_BACK=$IFS
    IFS=$'\n'
    branches=$(git branch -r)
    for branchName in $branches; do
        trimBranchName=`echo $branchName | xargs`
        canonicalBranchName=$(getCanonicalBranchName $trimBranchName '/')
        echo "$trimBranchName ($canonicalBranchName) init push"
        git checkout -b $canonicalBranchName remotes/origin/$canonicalBranchName
        git push -f gitlab $canonicalBranchName
    done
    IFS=$IFS_BACK
    cd ..
    rm -r -f $REPOSITORY
    echo "====================  <$REPOSITORY>  ===================="
    echo ""
done < "$REPOSITORIES"
 Contoh Output Konsol====================  <project>  ====================
Run cloning remote repository git@skynet-uro.bank.srv:project
Cloning into 'project'...
remote: Counting objects: 62, done.
remote: Compressing objects: 100% (61/61), done.
remote: Total 62 (delta 21), reused 0 (delta 0)
Receiving objects: 100% (62/62), 15.57 KiB | 0 bytes/s, done.
Resolving deltas: 100% (21/21), done.
Current folder path: /app/migration/project
Initialize remote gitgab repository git@127.0.0.1:project.git
Remote repository initialized identifier 222
Enable deploy key write access to remote repository project (222)
Set write access to remote repository project (222)
Add new remote url for repository git@127.0.0.1:project.git
Push to new remote gitlab repository git@127.0.0.1:project.git
Counting objects: 55, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (55/55), 14.65 KiB | 0 bytes/s, done.
Total 55 (delta 18), reused 50 (delta 16)
To git@127.0.0.1:project.git
 * [new branch]      master -> master
<--- gitlab/master (master) init push
fatal: A branch named 'master' already exists.
Everything up-to-date
---> gitlab/master (master) success pushed
<--- origin/v0.0.0 (v0.0.0) init push
Branch v0.0.0 set up to track remote branch v0.0.0 from origin.
Switched to a new branch 'v0.0.0'
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for v0.0.0, visit:
remote:   https://127.0.0.1:8082/project/merge_requests/new?merge_request%5Bsource_branch%5D=v0.0.0
remote:
To git@127.0.0.1:project.git
 * [new branch]      v0.0.0 -> v0.0.0
---> origin/v0.0.0 (v0.0.0) success pushed
<--- origin/v0.0.0-13 (v0.0.0-13) init push
Branch v0.0.0-13 set up to track remote branch v0.0.0-13 from origin.
Switched to a new branch 'v0.0.0-13'
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for v0.0.0-13, visit:
remote:   https://127.0.0.1:8082/project/merge_requests/new?merge_request%5Bsource_branch%5D=v0.0.0-13
remote:
To git@127.0.0.1:project.git
 * [new branch]      v0.0.0-13 -> v0.0.0-13
---> origin/v0.0.0-13 (v0.0.0-13) success pushed
<--- origin/v0.0.0-15 (v0.0.0-15) init push
Branch v0.0.0-15 set up to track remote branch v0.0.0-15 from origin.
Switched to a new branch 'v0.0.0-15'
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for v0.0.0-15, visit:
remote:   https://127.0.0.1:8082/project/merge_requests/new?merge_request%5Bsource_branch%5D=v0.0.0-15
remote:
To git@127.0.0.1:project.git
 * [new branch]      v0.0.0-15 -> v0.0.0-15
---> origin/v0.0.0-15 (v0.0.0-15) success pushed
<--- origin/v0.0.1 (v0.0.1) init push
Branch v0.0.1 set up to track remote branch v0.0.1 from origin.
Switched to a new branch 'v0.0.1'
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for v0.0.1, visit:
remote:   https://127.0.0.1:8082/project/merge_requests/new?merge_request%5Bsource_branch%5D=v0.0.1
remote:
To git@127.0.0.1:project.git
 * [new branch]      v0.0.1 -> v0.0.1
---> origin/v0.0.1 (v0.0.1) success pushed
<--- origin/v0.0.1-11 (v0.0.1-11) init push
Branch v0.0.1-11 set up to track remote branch v0.0.1-11 from origin.
Switched to a new branch 'v0.0.1-11'
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for v0.0.1-11, visit:
remote:   https://127.0.0.1:8082/project/merge_requests/new?merge_request%5Bsource_branch%5D=v0.0.1-11
remote:
To git@127.0.0.1:project.git
 * [new branch]      v0.0.1-11 -> v0.0.1-11
---> origin/v0.0.1-11 (v0.0.1-11) success pushed
<--- origin/v0.0.2 (v0.0.2) init push
Branch v0.0.2 set up to track remote branch v0.0.2 from origin.
Switched to a new branch 'v0.0.2'
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for v0.0.2, visit:
remote:   https://127.0.0.1:8082/project/merge_requests/new?merge_request%5Bsource_branch%5D=v0.0.2
remote:
To git@127.0.0.1:project.git
 * [new branch]      v0.0.2 -> v0.0.2
---> origin/v0.0.2 (v0.0.2) success pushed
<--- origin/v0.0.3 (v0.0.3) init push
Branch v0.0.3 set up to track remote branch v0.0.3 from origin.
Switched to a new branch 'v0.0.3'
Counting objects: 7, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 592 bytes | 0 bytes/s, done.
Total 4 (delta 3), reused 1 (delta 0)
remote:
remote: To create a merge request for v0.0.3, visit:
remote:   https://127.0.0.1:8082/project/merge_requests/new?merge_request%5Bsource_branch%5D=v0.0.3
remote:
To git@127.0.0.1:project.git
 * [new branch]      v0.0.3 -> v0.0.3
---> origin/v0.0.3 (v0.0.3) success pushed
====================  <project>  ====================