2017年6月份的時候,我就着手在公司推廣git,首先我自己嘗試搭建了GitLab來管理代碼,並且通過以下博客記錄了GitLab的搭建,以及GitLab備份,GitLab升級等事情。
- git學習——>在CenterOS系統上安裝GitLab並自定義域名訪問GitLab管理頁面
- git學習——>如何漢化GitLab?
- (轉)git學習——>Git 分支管理最佳實踐
- git學習——> Gitlab如何進行備份恢復與遷移?
- git學習——> 解決Gitlab 版本升級之后,發送 merge request 出現 http 500 的返回碼錯誤
- Git學習–>如何通過Shell腳本自動定時將Gitlab備份文件復制到遠程服務器?
- Git學習–>如何通過Shell腳本實現 監控Gitlab備份整個過程並且通過郵件通知得到備份結果?
- Git學習–>關於Jenkins編譯時候,如何獲取Git分支的當前分支名?
- Git學習–>GitLab如何屏蔽掉注冊功能?
- Git學習–>GitLab如何修改時區?
但是關於從SVN遷移到Git的具體操作到是沒有記錄下來,只記錄了一份博客。
現在想想,今年年初的時候,我們部門的軟件代碼已經全部成功遷移到了GitLab上,管理的項目已經達到300+,GitLab成員已經達到100+,Group分了60+來進行管理,整個管理起來有條不紊的,權限分配的都很合理。
現在我們來講一講,去年是怎么從SVN遷移到Git的,可能很多人這一步都很難走對。因為你要遷移過來,但是又不能將原來的SVN的commit記錄丟失,所以得用一套比較靠譜的方案。當時我自己用我自己的一份代碼做好了遷移test之后,輸出了一份《SVN項目遷移到Git操作指南》,然后將每個項目小組的組長包括Android、IOS、Html5等組長都培訓了一輪之后,大家都成功的將已有的SVN項目遷移到了GitLab上,后續的新項目都直接在GitLab上新建了。
下面以網易雲音樂為例,記錄SVN代碼倉庫遷移到GitLab倉庫的過程。
參考鏈接
在遷移的過程中,參考了以下的鏈接:
第一步、建立SVN用戶到git用戶的映射文件
在 Subversion,每個提交者在都在主機上有一個用戶名,記錄在提交信息中。如果想讓已有的信息更好的映射到 Git 作者數據里,則需要 從 Subversion 用戶名到 Git 作者的一個映射關系,因為Git是用郵箱來標識一個提交者的。建立一個叫做
userinfo.txt
的文件,每行一條svn作者 = 作者昵稱 <郵箱地址>
,用如下格式表示映射關系:
因為網易雲音樂這個項目有ouyangpeng和huxiaoqiao的提交記錄,所以userinfo.txt內容如下所示:
ouyangpeng = ouyangpeng <ouyangpeng@oaserver.dw.gdbbk.com> huxiaoqiao = huxiaoqiao <huxiaoqiao@oaserver.dw.gdbbk.com>
- 1
- 2
現在SVN代碼的文件中,使用如下命令獲取到所有提交者的名字。
SVN代碼的所有提交者的作者名可以通過以下命令獲得:
獲取svn提交的作者名
svn log --xml | grep "^<author" | sort -u | \awk -F '<author>' '{print $2}' | awk -F '</author>' '{print $1}' > userinfo.txt
- 1
得到以下文本,然后根據以上的格式編輯作者的郵件信息等。
lihongmeng
liyang
wangshuyin
wuqi
youpeng
ouyangpeng
- 1
- 2
- 3
- 4
- 5
- 6
這樣我們的把有svn的提交記錄的作者、郵箱userinfo.txt
都准備好了,接下來就克隆svn的地址。
lihongmeng = lihongmeng <lihongmeng@oaserver.dw.gdbbk.com> liyang = liyang <liyang@oaserver.dw.gdbbk.com> wangshuyin = wangshuyin <wangshuyin@oaserver.dw.gdbbk.com> wuqi = wuqi <wuqi@oaserver.dw.gdbbk.com> youpeng = youpeng <youpeng@oaserver.dw.gdbbk.com> ouyangpeng = ouyangpeng <ouyangpeng@oaserver.dw.gdbbk.com>
- 1
- 2
- 3
- 4
- 5
- 6
第二步、通過git svn clone克隆一個git版本庫,SVN里面包含trunk,branches和tags。
SVN版本庫的內容如下所示:
把上面的userinfo.txt 拷貝到 新建好的准備克隆svn代碼的git目錄下,
然后執行 git svn clone命令克隆一個git版本庫
git svn clone svn://172.28.1.171/XTCWatch_device_I3_APP/NetEaseCloudeMusic/ --no-metadata --authors-file=userinfo.txt --trunk=trunk --tags=tags --branches=branches
- 1
- 參數–no-metadata表示阻止git導出SVN包含的一些無用信息
- 參數–authors-file表示SVN賬號映射到git賬號文件,所有svn作者都要做映射
- 參數–trunk表示主開發項目
- 參數–branches表示分支項目
敲完命令后,會要求填寫SSH相關信息,填寫好svn的賬戶名和密碼 即可繼續執行。
填寫用戶名
填寫密碼
填寫完畢后,回車則會開始執行clone操作。
執行過程中,在不斷的從svn服務器拉取代碼到本地git版本庫
使用git log 命令查看轉換好的代碼庫,可以看到歷史記錄
widgetPhone的提交歷史記錄如下:
這個時候執行* git branch* 命令發現只有 master一個分支。
但是實際上我有好幾個分支,
APP_NetEaseCloudMusic_SearchSongs ,
APP_NetEaseCloudMusic_UseByAnonymous,
App_NetEaseCloudMusic_V0.1_backup
執行命令 git show-ref可以看到所有的引用,如下所示,
可以看到有master這個本地分支,同時有remote 分支trunk, APP_NetEaseCloudMusic_SearchSongs , APP_NetEaseCloudMusic_UseByAnonymous,
App_NetEaseCloudMusic_V0.1_backup 等,
通過Git Version 發現trunk 和 Master分支的版本是一樣的, 其他幾個分支和SVN客戶端branches 目錄下的結構是一樣的。 說明 git svn 將svn的主干和其他分支 轉換為了git的 master 和其他branch 。
這時我們發現有一些remote 分支,不是本地倉庫的分支, 我們還沒有設置remote, 那就需要執行以下的命令將remote 分支移回本地分支。
嘗試方法1
首先要移動標簽,把它們從奇怪的遠程分支變成實際的標簽,然后把剩下的分支移動到本地。要把標簽變成合適的Git標簽,運行
cp -Rf .git/refs/remotes/tags/* .git/refs/tags/ rm -Rf .git/refs/remotes/tags
- 1
- 2
該命令將原本以tag/開頭的遠程分支的索引變成真正的(輕巧的)標簽。
接下來,把refs/remotes下面剩下的索引變成本地分支:
cp -Rf .git/refs/remotes/* .git/refs/heads/ rm -Rf .git/refs/remotes
- 1
- 2
合並一起一共執行4條命令。
cp -Rf .git/refs/remotes/tags/* .git/refs/tags/ rm -Rf .git/refs/remotes/tags cp -Rf .git/refs/remotes/* .git/refs/heads/ rm -Rf .git/refs/remotes
- 1
- 2
- 3
- 4
- 5
- 6
- 7
嘗試方法2
在遷移 WidgetPhone 的時候,git/refs/remotes/tags/目錄不存在,而目錄.git/refs/remotes/origin/tags/存在,於是命令改為
cp -rf .git/refs/remotes/origin/tags/* .git/refs/tags/ rm -rf .git/refs/remotes/origin/tags cp -rf .git/refs/remotes/origin/* .git/refs/heads/ rm -rf .git/refs/remotes
- 1
- 2
- 3
- 4
- 5
- 6
- 7
現在所有的舊分支都變成真正的分支,所有的舊標簽也變成真正的標簽。
執行后效果如下所示,可以看到其他的branch都挪到了本地。
嘗試方法3
遷移 WidgetCommon 項目的時候,上面兩種命令都無效,都提示 .git/refs/remotes/origin/tags/* 目錄不存在,如下圖所示:
沒辦法,去官網查詢了下
使用如下的方法做操作。
首先要移動標簽,把它們從奇怪的遠程分支變成實際的標簽,然后把剩下的分支移動到本地。要把標簽變成合適的 Git 標簽,運行
$ git for-each-ref refs/remotes/tags | cut -d / -f 4- | grep -v @ | while read tagname; do git tag "$tagname" "tags/$tagname"; git branch -r -d "tags/$tagname"; done
- 1
該命令將原本以 tag/
開頭的遠程分支的索引變成真正的(輕巧的)標簽。
接下來,把 refs/remotes
下面剩下的索引變成本地分支:
$ git for-each-ref refs/remotes | cut -d / -f 3- | grep -v @ | while read branchname; do git branch "$branchname" "refs/remotes/$branchname"; git branch -r -d "$branchname"; done
- 1
第三步、添加遠程git服務器地址
1、添加遠程git remote 地址
在本地的倉庫中,增加遠程git remote 地址:
git remote add origin git@172.28.10.23:AndroidWatch/NetEaseCloudMusic.git
- 1
2、配置git 的 username 和 email
git config --global user.name ouyangpeng git config --global user.email ouyangpeng@oaserver.dw.gdbbk.com
- 1
- 2
- 3
下面是配置好的內容
3、執行* git push origin –all* 命令
然后執行* git push origin –all* 命令,推送到遠程Gitlab倉庫
$ git push origin --all
Counting objects: 7210, done. Delta compression using up to 8 threads. Compressing objects: 100% (5548/5548), done. Writing objects: 100% (7210/7210), 16.08 MiB | 9.68 MiB/s, done. Total 7210 (delta 3588), reused 0 (delta 0) remote: Resolving deltas: 100% (3588/3588), done. remote: GitLab: You are not allowed to push code to protected branches on this p roject. To 172.28.10.23:AndroidWatch/NetEaseCloudMusic.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'git@172.28.10.23:AndroidWatch/NetEaseCloudMu sic.git'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
如上圖所示,有可能push失敗,是因為master分支沒有給我授予權限push。
因為我是管理員,所以我在該項目中,設置我為master,如下圖所示:
將我設置我為master
然后就提交成功了。
DH207891+OuyangPeng@DH207891 MINGW32 /d/git test/AndroidWatch_NetEaseCloudMusic/ NetEaseCloudeMusic (master)
$ git push -u origin --all
Counting objects: 7210, done. Delta compression using up to 8 threads. Compressing objects: 100% (5548/5548), done. Writing objects: 100% (7210/7210), 16.08 MiB | 9.87 MiB/s, done. Total 7210 (delta 3586), reused 0 (delta 0) remote: Resolving deltas: 100% (3586/3586), done. To 172.28.10.23:AndroidWatch/NetEaseCloudMusic.git * [new branch] master -> master Branch master set up to track remote branch master from origin.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
4、執行 git push -u origin –tags 命令
如果你的項目有Tags的話,上面最后部分git push -u origin –all,運行之后並不能如它所說,分支和標簽(branches and tags)都在gitlab服務器中。
實際上,只提交了branches到gitlab上面,並沒有提交tags,當然,很簡單,你可以使用git push –h查看下幫助,就會發現,你應該知道怎么做了,使用git push –tags就可以了。
執行下面命令即可,由於網易並沒有建立tags,所以沒有任何代碼push到gitlab.
DH207891+OuyangPeng@DH207891 MINGW32 /d/git test/AndroidWatch_NetEaseCloudMusic/ NetEaseCloudeMusic (master)
$ git push -u origin --tags Everything up-to-date
- 1
- 2
- 3
- 4
第四步、查看gitlab上面是否正常提交
master分支
點擊master下拉框,切換分支
切換到 APP_NetEaseCloudMusic_SearchSongs 分支
查看commit 提交記錄
切換到 Branch 選項 可以查看所有的 Branch
第四步、定期同步SVN后續提交的代碼到Git倉庫
第一步,通過git show-ref
命令查看分支情況
其中 refs/remotes/git-svn 分支就是剛才用git svn clone 之后的遠程分支,可以在本地建立一個分支來同步svn后續的提交記錄
第二步,建立本地分支 local-git-svn 對應遠程分支git-svn
[root@xtgl207940 trunk]# git show-ref 9caa27cc211162aeed6e944144f4c676d2f1dfe1 refs/heads/develop 9caa27cc211162aeed6e944144f4c676d2f1dfe1 refs/heads/master 0ba94e3383d6f478844b1e674465fbc6ae0277e3 refs/remotes/git-svn 9caa27cc211162aeed6e944144f4c676d2f1dfe1 refs/remotes/origin/develop 62333dcb3beeb73e28538f815abfdfe791b88c00 refs/remotes/origin/local-git-svn 9caa27cc211162aeed6e944144f4c676d2f1dfe1 refs/remotes/origin/master [root@xtgl207940 trunk]# git checkout -b local-git-svn remotes/git-svn 切換到一個新分支 'local-git-svn' [root@xtgl207940 trunk]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
第三步,同步svn最新的提交記錄
使用 git svn fetch
命令同步SVN最新的提交記錄,然后可以通過 git log
命令查看git的提交記錄對應的svn記錄相同。
[root@xtgl207940 trunk]# git svn fetch [root@xtgl207940 trunk]# git log
- 1
- 2
- 3
第四步,切換分支到master分支,然后merge剛才的local-git-svn分支
[root@xtgl207940 trunk]# git checkout master 切換到分支 'master' 您的分支與上游分支 'origin/master' 一致。 [root@xtgl207940 trunk]# git branch develop local-git-svn * master [root@xtgl207940 trunk]# git merge local-git-svn 更新 9caa27c..0ba94e3 Fast-forward watch/src/main/java/com/xtc/watch/view/contact/activity/ContactPhoneActivity.java | 2 +- watch/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) [root@xtgl207940 trunk]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
第五步,提交master分支到GitLab遠程倉庫
第六步,查看gitlab上的代碼
終於將之前寫好的指導文件遷移到了CSDN博客上,這份指導文件已經完成了它的歷史使命,因為我們團隊內部所有代碼都已經成功遷移到了GitLab上,SVN已經成為過去式,但是這份文件可以分享出來給有需要的人。