做網(wǎng)站 一級(jí) 二級(jí)2023年10月爆發(fā)新冠
文章目錄
- 前言
- 問(wèn)題的產(chǎn)生
- 探索解決方案
- 正式的解決方法
- 背后的故事
- 總結(jié)
前言
TortoiseSVN
作為版本控制常用的工具,有一個(gè)更為人們熟知的名字 SVN
,客觀的講SVN的門檻相比Git而言還是低一些的,用來(lái)存儲(chǔ)一些文件并保留歷史記錄比較方便,但使用SVN還是會(huì)經(jīng)常需要這樣那樣的問(wèn)題,特別是當(dāng)倉(cāng)庫(kù)很大的時(shí)候,提示的問(wèn)題往往讓初學(xué)者、甚至是經(jīng)常使用的人一臉懵,比如這個(gè) Checksum mismatch for
問(wèn)題,通常SVN問(wèn)題都有一個(gè)終極解法,那就是重新克隆一份再操作,這就像大多數(shù)的電腦問(wèn)題重啟后就能解決一樣,不過(guò)偶爾有一些情景不適合采用重新克隆的解法,我們就得想一個(gè)更精確的辦法去解決了。
問(wèn)題的產(chǎn)生
在克隆一個(gè)300多G的庫(kù)時(shí),報(bào)了下面這個(gè)錯(cuò)誤,總結(jié)來(lái)說(shuō)這個(gè)錯(cuò)誤表述的就是“心有所求而不得”,期望得到一個(gè)md5是 2c448c9f40b0dd561539b80ec3cfcaa2
的 bundle_103_cp_delafere_e_buff_wuqi.ab
文件,但是下載后的文件計(jì)算md5得到的是 a2e41ec2779a23d88b31e4237ad43ceb
,并不是自己想要的,提示如下:
Error: Checksum mismatch for
Error: 'E:\gameproject\prefabs\bundle_103_cp_delafere_e_buff_wuqi.ab':
Error:
Error: expected: 2c448c9f40b0dd561539b80ec3cfcaa2
Error: actual: a2e41ec2779a23d88b31e4237ad43ceb
探索解決方案
先說(shuō)說(shuō)網(wǎng)上一些常見(jiàn)的解決辦法:
- 刪除了整個(gè)庫(kù),重新克隆下載,這個(gè)方法99%可行,但是整個(gè)庫(kù)太大了,我不想重新下載
Clean up
之后繼續(xù)更新,我試過(guò)了不行- 先在出錯(cuò)的文件夾下執(zhí)行
svn update --set-depth empty
刪除文件夾下所有文件,再執(zhí)行svn update --set-depth infinity
更新,這是流傳的最廣的解決辦法,在我這不行 - 先在
Update to revision...
中選擇 Update Depth 為Only this item
更新,然后再選擇Fully recursive
更新,原理上和上一步類似,在我這也不行
其實(shí)仔細(xì)分析這幾種解決方案的本質(zhì),都是把錯(cuò)誤的文件刪除掉再重新更新,但是為什么不起作用呢?
從我最終解決問(wèn)題的方法來(lái)看是,針對(duì)我遇到的問(wèn)題,上面提到的一些方法并沒(méi)有將錯(cuò)誤的文件成功刪除,簡(jiǎn)單分析下svn克隆和更新的過(guò)程,很可能不準(zhǔn)確,但是我不在此處不深究,暫時(shí)還用不到這一塊。
我們?cè)趥鬏斘募r(shí)為了保證文件的完整性,經(jīng)常會(huì)用一些摘要算法比如md5、sha1等來(lái)計(jì)算文件摘要,通過(guò)比較文件摘要來(lái)判斷文件傳輸是否完整,而SVN這個(gè)工具每時(shí)每刻都在上傳下載傳輸文件,所以也用到了摘要比對(duì)的技術(shù)。
以較新的SVN版本為例,是將sha1和md5存到了.svn/wc.db
中(太老的版本md5是存儲(chǔ)到文件中的),下載時(shí)先更新 wc.db
,然后將原始文件的元文件下載到 .svn/pristine
文件夾中,然后比較這些文件的md5值與 wc.db
記錄的md5值是否一致,如果一樣就從元文件中提取出真正的文件放到庫(kù)中,這個(gè)文件就算下載完了,如果不一致就會(huì)報(bào)出上面的錯(cuò)誤。
分析過(guò)后我們只要找到錯(cuò)誤的元文件,刪除后重新下載就解決了。
正式的解決方法
首先打開(kāi)從 .svn/wc.db
中查找的元文件的名字,可以使用你熟悉的工具,我用的是 SQLiteSpy.exe
有圖形界面方便一下,最基礎(chǔ)的也可以用 sqlite3.exe
這種命令行的工具,執(zhí)行以下sql語(yǔ)句:
select * from NODES where local_relpath = 'prefabs/bundle_103_cp_delafere_e_buff_wuqi.ab'
執(zhí)行過(guò)后可以查到checksum列的值為 $sha1$f9fd60e244a004cc30fcc83e8e59e7466b3dca6a
,這就是元文件的名字,也可以通過(guò)下面的語(yǔ)句查到md5值
select * from PRISTINE where checksum = '$sha1$f9fd60e244a004cc30fcc83e8e59e7466b3dca6a';
結(jié)果中md5_checksum列的值為 $md5$2c448c9f40b0dd561539b80ec3cfcaa2
就是報(bào)錯(cuò)中提到的那個(gè)期望值了。
接下來(lái)進(jìn)入 .svn/pristine/f9
文件夾,刪除 f9fd60e244a004cc30fcc83e8e59e7466b3dca6a.svn-base
文件,然后在倉(cāng)庫(kù)根目錄更新就正常了
背后的故事
問(wèn)題解決了,那么產(chǎn)生的這種問(wèn)題的原因是什么呢?為什么會(huì)md5值不一致呢?我們知道文件的md5值是根據(jù)文件內(nèi)容計(jì)算出來(lái)的,下載后的文件md5不是預(yù)期的值說(shuō)明文件內(nèi)容發(fā)生了變化。
我用比較工具對(duì)比了正常的文件和出錯(cuò)的文件發(fā)現(xiàn),兩個(gè)大小都為29949字節(jié)的文件,其中有一個(gè)字節(jié)發(fā)生了偏差,正確的文件該字節(jié)值為 2F
,而錯(cuò)誤的文件對(duì)應(yīng)值為 2E
,就弄錯(cuò)了這一個(gè)字節(jié),導(dǎo)致SVN的文件比對(duì)報(bào)錯(cuò)了。
這一個(gè)字節(jié)差異產(chǎn)生的原因,可能有很多種,比如傳輸過(guò)程中數(shù)據(jù)損壞、壓縮或加密問(wèn)題、數(shù)據(jù)損壞或硬盤問(wèn)題,我這里大概率是因?yàn)橄螺d時(shí)機(jī)器重啟的原因。
這讓我想起了7、8年前下載游戲服務(wù)器包無(wú)法啟動(dòng)的問(wèn)題,當(dāng)時(shí)下載完啟動(dòng)各種異常,比較文件大小也是一樣的,但是計(jì)算md5后發(fā)現(xiàn)不同,應(yīng)該也是傳輸過(guò)程中發(fā)生了錯(cuò)誤。
總結(jié)
- SVN遇到的問(wèn)題有90%都可以通過(guò)完整刪除后重新克隆下載的方式解決
- 老版本的文件checksum值存儲(chǔ)到
.svn/entries
文件中,較新版本的文件將這些值存儲(chǔ)在.svn/wc.db
中 - 通過(guò)
select * from NODES where local_relpath = 'xxx'
方式可以從.svn/wc.db
中查到文件的 sha1值 - 在
svn/pristine
中找到$sha1$.svn-base
刪除即可重新下載了
待到秋來(lái)九月八,我花開(kāi)后百花殺。有些句子在經(jīng)歷了一些事以后,自然而然就有了新的理解,這與兒時(shí)死記硬背下來(lái)的賞析是完全不同的~