#0 系列目錄#git
不少有點歷史的項目,都是用的 Subversion 做爲版本控制工具的,隨着項目須要,不少團隊就打算採用 Git 做爲替代工具了。好,如今問題來了:項目如何平滑的從 Subversion 遷移到 Git
。github
這裏所謂的遷移是按照版本控制要求來遷移,包括:app
儘量完整的由誰提交的代碼、作出的代碼變動記錄,提交日誌等。svn
儘量完整的分支、標籤等。工具
由於畢竟是不一樣的版本控制工具,轉化過程不免會有瑕疵。佈局
#1 準備環境# 安裝用到的工具的軟件包,這裏以 Ubuntu 爲例:.net
$ sudo apt-get install subversion git $ sudo apt-get install git-core libsvn-perl perl libterm-readkey-perl
#2 規範 Subversion# 確認項目的 Subversion 地址:版本控制
# 後面統一用 $PROJECT 表示項目的 Subversion 地址 # 這裏的示例項目名稱是 west https://scms.example.com/svn/projects/west/
規範項目在 Subversion 的目錄結構:日誌
標準的 trunk、branches、tags 目錄佈局。code
branches 和 tags 目錄下的分支和標籤保持平級,例如:
tags/v1.0.0 能夠。
tags/1.x/v1.0.0 多了層目錄就不能夠。
若是不是平級,以 tags 爲例,先執行 svn mv 操做。
方式 1 - 遠程 svn mv
$ svn mv $PROJECT/tags/1.x/v1.0.0 $PROJECT/tags/v1.0.0
方式 2 - 本地 svn mv
$ svn co $PROJECT west_subversion $ cd west_subversion $ svn mv tags/1.x/v1.0.0 tags/v1.0.0
最後規範後的目錄示例以下:
west ├── trunk │ ├── docs │ ├── west │ ├── setup.py │ └── README.rst ├── branches │ ├── hotfix_add_user_error │ ├── hotfix_issuse_9527 │ ├── feature_unittest4app │ └── feature_multi_add_user └── tags ├── v1.0.0 ├── v1.0.1 ├── v2.0.0 └── v2.1.0
#3 生成提交者 ID 和郵箱#
svn log $PROJECT --xml | grep -P "^<author" | \sort -u | perl -pe 's/<author>(.*?)</author>/$1 = $1 <$1@example.com>/' > users.txt
#4 遷出項目代碼(git svn)#
git svn clone $PROJECT --authors-file=users.txt --no-metadata --localtime --stdlayout
--authors-file 是獲得的 git log 提交記錄映射好提交者的信息;
--no-metadata 是獲得的 git log 不帶上對應的 Subversion 信息了,更乾淨;
--localtime 是獲得的 git log 以本地時間爲準,建議用上;
--stdlayout 是先前準備的按規範目錄風格來遷出代碼;
#5 轉化成Git的倉庫格式(tags 和 branches)# 處理 tag:
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
處理 branch:
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
#6 一些清理工做# 因爲這個轉化會將及歷史上的 branches 和 tags 也都生成一個 Git 的分支和標籤,因此仍是得清理下你認爲不用的分支和標,可能包括:
Subversion 歷史上錯誤的 tags。
Subversion 歷史上臨時的 branches。
冗餘的 trunk 分支(其實跟轉化後的 Git master 分支同樣)。
#7 添加到遠程 Git 倉庫#
git remote add origin git@github.com:akun/west.git git push origin --all git push origin --tags
#8 完成遷移# 這樣,能夠直接在 Git 下來繼續你的項目了。
git clone git@github.com:akun/west.git
#9 遺留問題# 上述方式轉化其實還有瑕疵,好比:
Subversion 容許空目錄,轉化 Git 用 git svn,處理空目錄帶上 --preserve-empty-dirs 可能會報錯,不處理,可能項目的程序原先依賴空目錄的處理就得修改。
相似 svn:externals,svn:ignore,svn:merge 等屬性丟失
不過問題不大,能夠接受,Subversion 遷移 Git 算是基本平滑遷移。