背景:
SVN和Git同樣都是在特定時(shí)代下比較優(yōu)秀的版本控制系統(tǒng)京办,但是隨著時(shí)代的發(fā)展矛缨,SVN越來(lái)越不能滿(mǎn)足多人開(kāi)發(fā)的需求,尤其是在多種多樣舶担,天馬星空的業(yè)務(wù)場(chǎng)景面前坡疼,SVN會(huì)顯得力不從心,而Git也慢慢的成為趨勢(shì)柄沮。
最近在將公司的項(xiàng)目從SVN遷移到git回梧,踩了不少坑,所以來(lái)記錄下:
因?yàn)檫w移的快慢和整個(gè)倉(cāng)庫(kù)的大小祖搓,電腦配置有關(guān)狱意,所以我先說(shuō)下這邊的情況
倉(cāng)庫(kù):
倉(cāng)庫(kù)大概是3.5G左右,包含了14500+的提交次數(shù)拯欧,其中包含了超過(guò)500M的單個(gè)文件-
電腦:
電腦配置就看圖吧 :
在以上兩種情況下详囤,排除掉采坑的時(shí)間,總耗時(shí)在10小時(shí)左右镐作,當(dāng)時(shí)中途我也用過(guò)一臺(tái)聯(lián)系X1的本嘗試過(guò)藏姐,配置如下:
后來(lái)聯(lián)想這臺(tái)電腦放棄了,因?yàn)榭偤臅r(shí)已經(jīng)超過(guò)30小時(shí)该贾,
操作:
生成作者文件:
因?yàn)槲覀冎栏嵫睿赟VN上提交和在Git上提交對(duì)應(yīng)提交者的信息展示是不同的,SVN只會(huì)保存一個(gè)用戶(hù)名杨蛋,而Git會(huì)保存該用戶(hù)的郵箱兜材,所以我們遷移的第一步就要生成一個(gè)映射文件,將SVN上的用戶(hù)名和其郵箱對(duì)應(yīng)起來(lái),就比如 molier = molier <371099694@qq.com>
,轉(zhuǎn)換的辦法有很多逞力,如果你團(tuán)隊(duì)里面的人不是很多的是時(shí)候,可以自己去提交記錄中手動(dòng)生成這樣一個(gè)TXT文件
XXX = XXX <XXX@XXX.com>
XXX = XXX <XXX@XXX.com>
.
.
.
.
但是如果曙寡,多人開(kāi)發(fā)人數(shù)很多的時(shí)候,手動(dòng)轉(zhuǎn)很累,我們就需要一個(gè)Atlassian的工具包 svn-migration-scripts.jar寇荧,通過(guò)命令拉取SVN倉(cāng)庫(kù)的用戶(hù)并生成對(duì)應(yīng)的開(kāi)發(fā)者信息映射文件举庶,需要Java運(yùn)行時(shí)環(huán)境支持,大家可能還需要安裝JDK:
java -jar svn-migration-scripts.jar authors https://svn.example.com > authors.txt
這樣之后會(huì)在當(dāng)前目錄生成一個(gè) authors.txt
文件
轉(zhuǎn)換倉(cāng)庫(kù)
-
整體轉(zhuǎn)換
-
標(biāo)準(zhǔn)的SVN文件布局:
如果SVN倉(cāng)庫(kù)使用標(biāo)準(zhǔn)的了/trunk, /branches和/tags的目錄結(jié)構(gòu),就可在運(yùn)行命令時(shí)加上參數(shù)--stdlayout揩抡,使用如下命令
git svn clone --stdlayout --authors-file=authors.txt <svn-repo>/<project> <克隆到文件夾的名字>
-
非標(biāo)準(zhǔn)的的SVN文件布局:
如果SVN倉(cāng)庫(kù)是非標(biāo)準(zhǔn)的目錄布局户侥,那就需要分別顯示指定參數(shù)--trunk, --branches, --tags镀琉。
git svn clone --trunk=/trunk --branches=/branches --branches=/bugfixes --tags=/tags --authors-file=authors.txt <svn-repo>/<project> <克隆到文件夾的名字>
-
-
部分轉(zhuǎn)換
如果倉(cāng)庫(kù)非常龐大的話(huà)可以選擇部分轉(zhuǎn)換,也就只轉(zhuǎn)換指定提交之后的提交添祸,可以試用如下代碼
git svn clone -r123456:HEAD --stdlayout --authors-file=authors.txt <svn-repo> <克隆到文件夾的名字>
不過(guò)這里需要注意的是如果使用這種方式來(lái)轉(zhuǎn)換那么一定要指定SVN的代碼根部滚粟,而不能指定分支,因?yàn)镾VN的提交編號(hào)都是按照時(shí)間順序來(lái)往下依次排列刃泌,不同的分支也可能提交編號(hào)是連續(xù)的凡壤,所以如果只關(guān)心編號(hào)的話(huà)就不能再指定分支了。
以上三步中所用到的 authors.txt
即為上一步所生成的耙替,作者 -> 作者 <作者郵箱>
的對(duì)應(yīng)關(guān)系文件.
坑點(diǎn)
完成以上操作的話(huà)如果一切正常那么你就會(huì)獲得一個(gè)新的Git倉(cāng)庫(kù)亚侠,然后就可以添加到遠(yuǎn)端,進(jìn)行多人開(kāi)發(fā)了俗扇,至于git的操作并不在本文的范圍內(nèi)硝烂,下面會(huì)講一下遇到的坑以及解決辦法。
坑點(diǎn)一:時(shí)間久
轉(zhuǎn)換倉(cāng)庫(kù)是比較耗時(shí)的铜幽,因?yàn)樗麜?huì)一個(gè)提交一個(gè)提交的轉(zhuǎn)換滞谢,轉(zhuǎn)換的速度和你的倉(cāng)庫(kù)提交次數(shù)和電腦配置成正比,我當(dāng)時(shí)轉(zhuǎn)了十幾個(gè)小時(shí)比較正常除抛,而且轉(zhuǎn)換完之后他還有個(gè)自己整理文件的過(guò)程也是很耗時(shí)的狮杨,不過(guò)如果你選擇部分轉(zhuǎn)換的話(huà)也可能很快,假如你一共15000個(gè)提交到忽,然后你從14999來(lái)轉(zhuǎn)換可能幾分鐘就夠了橄教。當(dāng)然最好的辦法就是下班前開(kāi)始執(zhí)行,第二天來(lái)了基本就差不多了喘漏。不過(guò)別高興的太早护蝶,請(qǐng)看坑點(diǎn)二。
坑點(diǎn)二:垃圾過(guò)多導(dǎo)致暫停
因?yàn)槭且闅v所有的歷史提交翩迈,所以可能會(huì)有很多的無(wú)用文件 比如項(xiàng)目一開(kāi)始代文件結(jié)構(gòu)很亂持灰,然后慢慢的經(jīng)過(guò)重構(gòu),之類(lèi)的優(yōu)化步入正軌负饲,這過(guò)程中必然會(huì)刪掉大量的無(wú)用搅方、冗余的文件,雖然這些文件已經(jīng)不復(fù)存在了绽族,但是提交記錄會(huì)有,而且通過(guò)git的原理來(lái)看他還是會(huì)把這些東西一一保存下來(lái)衩藤,所以就會(huì)造成大量無(wú)用的文件越來(lái)越多吧慢,而Git是有一個(gè)緩沖區(qū)(具體大小不確定?)當(dāng)你無(wú)用文件把緩沖區(qū)沾滿(mǎn)了,那么轉(zhuǎn)換過(guò)程會(huì)停止會(huì)爆出如下錯(cuò)誤
Auto packing the repository in background for optimum performance.
See "git help gc" for manual housekeeping.
error: The last gc run reported the following. Please correct the root cause and remove .git/gc.log.
Automatic cleanup will not be performed until the file is removed.
warning: There are too many unreachable loose objects; run 'git prune' to remove them.
gc --auto: command returned error: 255
大概意思是垃圾太多赏表,轉(zhuǎn)移暫停讓你先清理垃圾检诗,其實(shí)只要按照他說(shuō)的 進(jìn)到我們轉(zhuǎn)了一半的倉(cāng)庫(kù) 進(jìn)行 git gc
就可以匈仗,但是這樣一來(lái)我們就需要一直守在電腦前,隨時(shí)準(zhǔn)備輸入 git gc
而且假如你下班前開(kāi)始跑結(jié)果第二天上班一看跑到一半就暫停了逢慌,白白浪費(fèi)了一晚上的時(shí)間悠轩,真的會(huì)崩潰的。所以通過(guò)google找到了解決辦法
也就是開(kāi)始轉(zhuǎn)換的時(shí)候先進(jìn)入倉(cāng)庫(kù)輸入 git config gc.auto 0
關(guān)閉gc功能攻泼,然后就可以一直跑到黑了火架,你大可以放心的運(yùn)行命令然后下班回家。不過(guò)還有一點(diǎn)需要注意的是垃圾文件是否過(guò)多和你倉(cāng)庫(kù)大小沒(méi)有太大關(guān)系忙菠,及時(shí)你倉(cāng)庫(kù)提交不多何鸡,但是每次提交都有很大改動(dòng)的話(huà)也還是會(huì)出現(xiàn)這個(gè)問(wèn)題,所以這里建議不管你倉(cāng)庫(kù)多大牛欢,都要先進(jìn)行一下這個(gè)操作骡男,以防萬(wàn)一。
坑點(diǎn)三:大文件處理
git和SVN不同傍睹,在git上提交的單個(gè)文件是有大小限制的隔盛,超過(guò)這個(gè)大小就不允許提交到倉(cāng)庫(kù)中,通常我們會(huì)用git LFS來(lái)解決拾稳,具體的安裝吮炕,添加步驟網(wǎng)上大把的教程,就不在這里說(shuō)熊赖,不過(guò)他只會(huì)告訴你大文件的大小和限制的大小来屠,具體的大文件是哪個(gè)他不會(huì)告訴你,這里可以用以下命令查看
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
他會(huì)輸出前五個(gè)最大的文件震鹉,然后你再按需處理俱笛。但是當(dāng)你把大文件添加到LFS中后再次推送還是會(huì)爆出同樣的錯(cuò)誤,而且還是同樣的文件传趾,也就是說(shuō)你根本沒(méi)添加成功迎膜,其實(shí)并不是這樣的,在添加LFS中只要你操作沒(méi)錯(cuò)浆兰,就是添加成功了磕仅,他還會(huì)報(bào)錯(cuò)的原因是因?yàn)殡m然你工程中的大文件已經(jīng)添加,但是你的歷史提交記錄中是包含大文件的代碼快照的簸呈,所以你需要將歷史上所有包含大文件的提交記錄重寫(xiě)榕订,刪掉大文件相關(guān)的東西,git 中重寫(xiě)commit的命令是:
git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch 你大文件所在的目錄' --prune-empty --tag-name-filter cat -- --all
這個(gè)過(guò)程也比較漫長(zhǎng)蜕便,他會(huì)便利你所有的提交記錄并一一修改劫恒,不過(guò)就是漫長(zhǎng)的等待就可以了,等到完成之后我們需要將代碼push到遠(yuǎn)端,因?yàn)槲覀冃薷牧怂械腸ommit 我們需要強(qiáng)制push使用如下命令
git push origin master --force
坑點(diǎn)四: 打包時(shí)間過(guò)長(zhǎng)
再上一步我們執(zhí)行完推送命令的時(shí)候两嘴,會(huì)先進(jìn)行文件打包處理丛楚,這個(gè)過(guò)程也是非常漫長(zhǎng),而且非常消耗電腦資源的憔辫,按照我的電腦配置來(lái)說(shuō)趣些,這個(gè)過(guò)程一旦開(kāi)始,電腦基本就是內(nèi)存贰您、cpu全滿(mǎn)的狀態(tài)坏平,鼠標(biāo)也沒(méi)法動(dòng),所以這個(gè)過(guò)程要有心理準(zhǔn)備枉圃。漫長(zhǎng)的等待之后就推送成功了功茴。
總結(jié):
目前就這些問(wèn)題,如果誰(shuí)有其他的問(wèn)題歡迎去我的小站給我留言孽亲。