這些問題與目前 支援的版本 相關。對於較舊的問題,請參閱 下方。
不,Subversion 是開源/免費軟體。幾家公司(CollabNet、WANdisco、VisualSVN、elego,...)支付或曾支付一些全職開發人員的薪水,但軟體採用 Apache 授權,完全符合 Debian 自由軟體準則。換句話說,你可以自由下載、修改和重新分發 Subversion,無需任何公司或個人的許可。
Subversion 非常穩定。它是一款成熟的軟體,具有強大的 相容性保證。Subversion 開發社群非常重視其穩定性和健壯性。
Subversion 自 2000 年開始開發,並於一年後成為自託管。一年後,當我們宣佈「alpha」時,Subversion 已被數十位私人開發人員和商店用於實際工作。在那之後,我們又花了兩年的時間修復錯誤和穩定程式,才達到 1.0。大多數其他專案可能早就將產品稱為「1.0」,但我們故意決定盡可能延後這個標籤。我們知道許多人都在等待 1.0 才使用 Subversion,而且對這個標籤的意義有非常具體的期望。因此,我們堅持相同的標準。
用戶端和伺服器設計為只要它們的版本號不超過一個主要版本,就能一起運作。例如,任何 1.X 用戶端都能與 1.Y 伺服器一起運作。但是,如果用戶端和伺服器版本不匹配,某些功能可能無法使用。此類限制總是記錄在我們發行的 發行說明 中。
我們的用戶端/伺服器互通性政策記載於 Subversion 社群指南 的「相容性」區段中。
所有現代版本的 Unix、Windows、BeOS、OS/2、macOS。
Subversion 以 ANSI C 編寫,並使用 Apache Portable Runtime 函式庫 APR 作為可攜層。Subversion 用戶端可以在 APR 能執行的任何地方執行,也就是大多數地方。Subversion 伺服器(即儲存庫端)也是一樣,但它不會在 Win9x 平台(Win95/Win98/WinME)上主機 Berkeley DB 儲存庫,因為 Berkeley DB 在 Win9x 上有共用記憶體區段的問題。FSFS 儲存庫(在版本 1.1 中引入)沒有這個限制;但是,由於 Win9x 的檔案鎖定支援有限,它們也不適用於 Win9x。
重申一次,Subversion 客户端可以在任何运行 APR 的平台上运行。Subversion 服务器也可以在任何运行 APR 的平台上运行,但不能在 Win95/Win98/WinMe 上托管存储库。
不。Subversion 文件系统不是内核层文件系统,人们会将其安装在操作系统中。相反,它是 Subversion 的存储库界面,它是一个版本化文件系统,因为它存储了一个目录树,其状态从一个版本记住到另一个版本。编写程序来访问存储库类似于编写使用其他文件系统 API 的程序。主要区别在于此特定文件系统在写入时不会丢失数据;可以像检索最新状态一样轻松地检索旧树状态。
服务器需求取决于许多因素,例如用户数量、提交频率和其他服务器相关操作、存储库大小以及自定义存储库钩子产生的负载。在使用 Apache 时,Apache 本身很可能是内存使用量最大的因素。
请记住考虑在同一服务器上运行的其他应用程序;例如,存储库浏览器也会使用资源,而与 Subversion 本身无关。
一般来说,您可以预期需要的服务器内存比同等 CVS 存储库少得多。
編號。Subversion 是一組函式庫。它附帶一個使用它們的命令列用戶端。有兩個不同的 Subversion 伺服器程序:svnserve,這是一個類似於 cvs pserver 的小型獨立程式,或使用特殊 mod_dav_svn 模組的 Apache httpd-2.0。svnserve 使用自訂協定,而 mod_dav_svn 使用 WebDAV 作為其網路協定。請參閱 Subversion 書籍中的 第 6 章 以進一步了解。
簡短的答案:否。
詳細的答案:如果您只想存取儲存庫,那麼您只需要建置一個 Subversion 用戶端。如果您想主機一個網路儲存庫,那麼您需要設定 Apache2 或「svnserve」伺服器。
有關設定網路可存取 Subversion 伺服器的更多詳細資訊,請參閱 Subversion 書籍中的 第 6 章。
否,您可以執行 svnserve 作為 Subversion 伺服器。它運作得非常好。
如果您想要 WebDAV 和 Apache 伺服器附帶的所有其他「好處」,那麼是的,您將需要 Apache 2.0。在繼續於埠 80 上執行 Apache 1.x 的同時,在不同的埠上執行 Apache 2.0 始終是一個選項。不同版本的 Apache 可以愉快地共存在同一台機器上。只要將 httpd.conf 中的 Listen 指令從「Listen 80」變更為「Listen 8080」或您想要的任何埠號,並確保在發佈儲存庫 URL 時指定該埠(例如,http://svn.mydomain.com:8080/repos/blah/trunk/)。
首先,請注意 Subversion 沒有專案的概念。儲存庫僅儲存版本化的目錄樹 — 您可能會將某些子樹視為專案,但 Subversion 並不會將它們與其他子樹區別對待。因此,儲存庫中專案的解釋完全取決於使用者。(這類似於 分支 和 標籤 是建立在複製之上的慣例,而不是 Subversion 本身內建的基本概念。)
每次您提交變更時,儲存庫會儲存該整體儲存庫樹的新版本,並標記新樹為新的版本號碼。當然,除了您變更的部分之外,大部分樹與之前的版本相同。
新的版本號碼是適用於整個新樹的順序標籤,而不仅仅是您在該版本中觸及的檔案和目錄。然而,在口語中,版本號碼用於指稱在該版本中提交的變更;例如,「r588 中的變更」(「r588」是「版本 588」的簡稱)實際上表示「儲存庫樹 587 和 588 之間的差異」,或換句話說,「對樹 587 進行的變更以產生樹 588」。
因此,前進的版本號標記了整個儲存庫的進度;您通常無法透過觀察版本號來評估儲存庫中特定專案的進度。此外,版本號不應當作儲存庫中特定專案的公開可見發布號碼。對於這一點,您應設計其他機制來區分發布,例如使用 標籤。
這個問題有點沉重,因為每個人似乎對於「變更集」都有略微不同的定義,或至少對於版本控制系統擁有「變更集功能」的意義有略微不同的期待。
為了這個討論的目的,以下是變更集的簡單定義:它是一個具有唯一名稱的變更集合。變更可能包括檔案內容的文字編輯、樹狀結構的修改或元資料的調整。用更通俗的說法,變更集只是一個您可以引用的具有名稱的修補程式。
Subversion 將版本化樹狀結構管理為一階物件(儲存庫是樹狀結構陣列),而變更集是衍生的東西(透過比較相鄰樹狀結構)。Arch 或 Bitkeeper 等系統則是以相反的方式建構:它們被設計為將變更集管理為一階物件(儲存庫是一袋修補程式),而樹狀結構則透過將修補程式集合組合在一起而衍生出來。
這兩種哲學在絕對意義上都沒有比較好:這場辯論至少已經持續 30 年。這兩種設計對於不同類型的軟體開發來說各有優劣。我們在此不討論這個問題。相反地,以下是您可以使用 Subversion 執行的說明。
在 Subversion 中,全域版本號碼「N」會為儲存庫中的樹狀結構命名:這是儲存庫在第 N 次提交後的樣貌。它也是隱含變更集的名稱:如果你將樹狀結構 N 與樹狀結構 N-1 進行比較,你可以導出已提交的確切修補程式。
基於這個原因,很容易將「版本 N」視為不只是樹狀結構,也是變更集。如果你使用問題追蹤器來管理錯誤,你可以使用版本號碼來參考修正錯誤的特定修補程式,例如「此問題已由版本 9238 修復」。然後,有人可以執行「svn log -r9238」來閱讀已修正錯誤的確切變更集,並執行「svn diff -r9237:9238」來查看修補程式本身。而 svn 的合併指令也使用版本號碼。你可以透過在合併參數中命名特定變更集,將它們從一個分支合併到另一個分支:'svn merge -r9237:9238 branchURL' 會將變更集 #9238 合併到你的工作副本中。
這遠遠不及建構在變更集作為主要物件的系統那麼複雜,但它仍然比 CVS 方便許多。
Subversion 1.1(及後續版本)有能力透過一般的 svn add 指令,將(unix)符號連結置於版本控制之下。
詳細資訊:Subversion 儲存庫沒有符號連結的內部概念。它將「已版本化的符號連結」儲存為附加有「svn:special」屬性的普通檔案。svn 客户端(在 unix 上)會看到屬性,並將檔案轉譯成工作副本中的符號連結。
在 Windows 上,svn 客户端目前不支持將版本化符號連結轉換為 Windows 符號連結變體(連接點等)之一。檢出的物件會顯示為一般檔案。一般來說,難以支援此功能的原因之一是,預設只有管理員可以在 Windows 上建立符號連結。如需更多資訊,請參閱 問題 SVN-3570。
提供以下 Subversion 標誌版本
Subversion 的原始程式碼樹中提供了一些其他圖稿,位於 notes/logo 和 此網站 中。
如果您瀏覽完此常見問題集後仍找不到答案,還有其他幾項可用的資源
我們的郵件清單會進行審核以防止垃圾郵件通過,因此您第一次發文到任何清單時可能會延遲,直到審核人員有機會讓它通過。一旦該文章被允許通過,來自同一個地址的所有後續文章都會自動核准,因此您應該不會再遇到延遲。當然,如果您的寄件地址變更,則必須再次通過審核。
DST 的變更不需要對 Subversion 程式碼進行任何特別的變更或修正。Subversion 主要使用日期/時間來記錄變更已提交到儲存庫的時間。此程式碼在伺服器上執行,並從作業系統取得目前的日期/時間,並使用作業系統提供的常式將其轉換為 UTC。Subversion 用戶端從伺服器接收這些日期,並使用用戶端作業系統提供的常式將其轉換為當地時區以顯示。因此,您應該只需要安裝作業系統提供的修補程式,而且您真的只需要確保伺服器上的時間已針對 DST 進行適當調整。
Google 和 CWI 發表了已知的首個 SHA-1 衝突,揭露了 Subversion 使用 SHA-1 的幾個相關問題。Subversion 的核心並未依賴 SHA-1 進行內容索引,但它在以下補充功能中用於此類目的
談到儲存庫資料重複刪除功能,這可能會導致無法存取具有衝突 SHA-1 值的檔案,或造成此類檔案的資料遺失。若要防止具有相同 SHA-1 的不同內容儲存在儲存庫中,請升級到 1.9.6 或 1.8.18,預設情況下,這會防止儲存具有此類衝突的資料。有關詳細資訊,請參閱我們的 SHA-1 建議。
在升級到這些新版本之前,基於 Unix 的伺服器可以使用在 這裡 找到的提交前掛鉤。順便一提,我們歡迎 Windows 開發人員提交 Windows 平台的提交前腳本。有關提交的更多資訊,請參閱 這裡。
工作副本使用 SHA-1 對儲存的內容進行重複刪除,並且出於效能原因,客戶端將避免擷取具有相同 SHA-1 檢查碼的內容。此問題的解決方法是從一開始就防止儲存衝突的物件,方法是升級到 1.9.6 或安裝上述提交前腳本。
儲存具有 SHA-1 衝突的內容並非受支援的使用案例。如果您有具有衝突 SHA-1 hash 值的內容,我們建議您在提交之前透過 gzip 轉換它,以完全避免衝突。此外,強烈建議升級到 1.9.6 以防止未來插入重複資料。
使用 Subversion 軟體用戶端
$ svn co https://svn.apache.org/repos/asf/subversion/trunk subversion
這將在您的本機上檢出 Subversion 原始碼樹的副本,並儲存在名為 subversion 的目錄中。
請參閱 快速入門。如需更多詳細資訊,請參閱 Subversion Book 中的快速入門說明。
如需有關儲存庫設定和管理的更多詳細資訊,請閱讀 Subversion Book 中的第 5 章。
cvs2svn 轉換工具似乎是大多數人使用的工具。原始碼寄存於 https://github.com/mhagger/cvs2svn。如果您執行的是 Linux 或 BSD 系統,您的發行版可能會有 cvs2svn 套件。
如果 cvs2svn 無法滿足您的需求,您可以嘗試 Lev Serebryakov 在 http://lev.serebryakov.spb.ru/refinecvs/ 編寫的 refinecvs。
Subversion 客戶端可以透過代理伺服器,如果您設定它這麼做。首先,編輯您的「伺服器」設定檔,以指出要使用哪個代理伺服器。檔案位置取決於您的作業系統。在 Linux 或 Unix 上,它位於「~/.subversion」目錄中。在 Windows 上,它位於「%APPDATA%\Subversion」中。(嘗試「echo %APPDATA%」,請注意這是一個隱藏目錄。)
檔案中有說明如何執行的註解。如果您沒有該檔案,請取得最新的 Subversion 客戶端並執行任何命令;這將導致建立設定目錄和範本檔案。
接下來,您需要確保代理伺服器本身支援 Subversion 使用的所有 HTTP 方法。預設情況下,某些代理伺服器不支援這些方法:PROPFIND、REPORT、MERGE、MKACTIVITY、CHECKOUT。一般而言,解決此問題取決於特定的代理軟體。對於 Squid,設定選項為
# TAG: extension_methods # Squid only knows about standardized HTTP request methods. # You can add up to 20 additional "extension" methods here. # #Default: # none extension_methods REPORT MERGE MKACTIVITY CHECKOUT
(Squid 2.4 和更新版本已經知道 PROPFIND。)
另請參閱「Subversion 使用的所有 HTTP 方法是什麼?」以取得有關允許透過代理伺服器傳輸其他 HTTP 方法的建議。
如果讓代理伺服器允許 Subversion 流量很困難或不可能,但您想要檢視 Subversion 原始碼,您可能可以繞過代理伺服器。某些過濾埠 80 的代理伺服器仍然允許埠 81 上的任何內容。在許多其他情況下,代理伺服器不會像過濾 http 那樣嚴格地過濾 https。 svn.apache.org 儲存庫伺服器在 https 和 http 上都會監聽。嘗試
svn checkout https://svn.apache.org/repos/asf/subversion/trunk subversion
代理伺服器可能會讓您通過。
當然,您的 svn 客戶端必須使用 ssl 支援來建置。您可以透過執行 svn --version 來檢查是否支援「https」架構。
如果 Subversion 伺服器未直接連接到網際網路,可以使用反向代理伺服器。它會將 HTTP/HTTPS 流量從公開伺服器轉發到 Subversion 伺服器,可能會移除 HTTPS 加密。如果必須在同一個埠上提供多個不同的 HTTP 伺服器,它也可能很有用。
Subversion 使用 WebDAV/DeltaV 協定的子集;請參閱 此常見問題解答項目 以取得詳細資訊。就代理伺服器而言,Subversion 使用純粹的 WebDAV 協定。對於 svn copy 和 svn move 指令,會使用額外的 HTTP_DESTINATION 標頭;這必須另外改寫。
針對幾個不同的代理伺服器提供詳細說明。從這些範例複製構想應該相當容易。
以下資訊根據 Konrad Rosenbaum 所撰寫的文章,最初在 http://silmor.de/proxysvn.php 上找到。經許可複製。
Apache 的代理端需要 mod_proxy 才能運作。在許多 Linux 發行版中,有可以啟用的現成組態檔,否則請在 httpd.conf 中插入此組態。
#load the module LoadModule proxy_module modules/mod_proxy.so #per default disallow all requests (for security) ProxyRequests Off <Proxy *> Order deny,allow Deny from all </Proxy> ProxyVia On
在代理虛擬主機的 VirtualHost 指令中,將對 Subversion 目錄的請求 (我們假設稱為 svn) 組態為中繼到實際的 Subversion 伺服器
ProxyPass /svn/ http://realsvnserver/svn/ <Location /svn/> ProxyPassReverse /svn/ http://realsvnserver/svn/ <Limit OPTIONS PROPFIND GET REPORT MKACTIVITY PROPPATCH PUT CHECKOUT MKCOL MOVE COPY DELETE LOCK UNLOCK MERGE> Order Deny,Allow Allow from all Satisfy Any </Limit> RewriteCond %{HTTP:Destination} .+/(svn/.*$) RewriteRule ^/svn/.* - [E=MyDestination:http://realsvnserver/%1,PT] RequestHeader set Destination %{MyDestination}e env=MyDestination </Location>
ProxyPass 指令指示 Apache 將 /svn 下方的請求重新導向到 Subversion-Apache (http://realsvnserver/svn)。ProxyPassReverse 指令指示它變更請求標頭 (位置、內容位置和 URI) 以符合目標伺服器 — 視 Apache 的版本及其組態而定,您可能需要略過 /svn/ 或 http://realsvnserver/svn/。如果可能,應在兩個伺服器上使用相同的路徑 (否則 DAV 可能會造成問題)。Limit 指令指示 Apache 允許所有來自所有用戶端的 DAV 請求 (允許) 通過,並讓實際的 Subversion 伺服器處理驗證 (滿足)。Rewrite 規則將 HTTP_DESTINATION 標頭更新為正確的伺服器/協定。
首先從 iis.net 下載並安裝 URL 重寫模組。以下範例已在 IIS 10 和 URL 重寫 2.1 中測試過。
接下來,將 URL 重寫組態為允許 HTTP_DESTINATION 伺服器變數:在 URL 重寫下的 IIS 管理員中,在右窗格中按一下「檢視伺服器變數」並新增 HTTP_DESTINATION。
最後建立一些改寫規則
<system.webServer> <rewrite> <rules> <clear /> <rule name="ToHttps" stopProcessing="true"> <match url="(.*)" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false"> <add input="{HTTPS}" pattern="^OFF$" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"/> </rule> <rule name="ProxyWithDestination" enabled="true" patternSyntax="ECMAScript" stopProcessing="true"> <match url="(.*)" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false"> <add input="{HTTP_DESTINATION}" pattern="https://(.*)"/> </conditions> <serverVariables> <set name="HTTP_DESTINATION" value="http://{C:1}" /> </serverVariables> <action type="Rewrite" url="http://127.0.0.1:81/{R:0}" logRewrittenUrl="true" /> </rule> <rule name="ProxyRest" patternSyntax="ECMAScript" stopProcessing="true"> <match url="(.*)" negate="false" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false" /> <action type="Rewrite" url="http://127.0.0.1:81/{R:0}" logRewrittenUrl="true" /> </rule> </rules> </rewrite> <security> <requestFiltering allowDoubleEscaping="true" /> </security> </system.webServer>
一個簡單的選項是使用 svnserve 伺服器,而不是 Apache。請參閱 Subversion 書籍中的 第 6 章,以取得詳細資料。
不過,如果您的管理員不希望您執行 Apache,他們很可能也不希望您在埠 3690 上執行自訂伺服器程序!因此,本答案的其餘部分假設您的管理員同意您使用現有的 SSH 基礎架構。
如果您先前曾使用 CVS,您可能已使用 SSH 登入 CVS 伺服器。ra_svn Subversion 存取方法是使用 Subversion 執行此項操作的等效方式。只要對您的 Subversion 儲存庫 URL 使用「svn+ssh」前置詞即可。
$ svn checkout svn+ssh://your.domain.com/full/path/to/repository
這會讓您的 SSH 程式在遠端方塊上啟動一個私人「svnserve」程序,該程序會以您的 UID 存取儲存庫,並透過加密連結將資訊傳輸回來。
不過,可以使用的另一種解決方案是利用 SSH 埠轉送,透過 ra_dav 連線至受保護的伺服器。您會透過 SSH 連線至防火牆後方,可以存取您的 Subversion 伺服器的機器。請注意,此 SSH 伺服器不一定與安裝 Subversion 的位置相同。可以相同,但不必相同。
然後,您建立連接到放置 Subversion 儲存庫的 HTTP 伺服器的本機埠轉送。然後,您會透過這個本機埠「連線」到 Subversion 儲存庫。然後,要求會透過 SSH 伺服器「隧道路由」傳送到您的 Subversion 伺服器。
範例:Subversion ra_dav 設定位於公司防火牆後方的 10.1.1.50(稱為 svn-server.example.com)。您的公司允許透過公開可存取的 ssh-server.example.com 存取 SSH。在內部,您可以透過 http://svn-server.example.com/repos/ours 存取 Subversion 儲存庫。
範例:透過埠轉送連線到 ssh-server 的用戶端,並透過埠轉送查看
% ssh -L 8888:svn-server.example.com:80 me@ssh-server.example.com % svn checkout https://127.0.0.1:8888/repos/ours
請注意,您的 svn-server.example.com 也可以讓其 httpd 執行個體由非受信任使用者在非特權埠上執行。這將允許您的 Subversion 伺服器不需要 root 存取權。
Joe Orton 筆記
The server is sensitive to the hostname used in the Destination header in MOVE and COPY requests, so you have to be a little careful here - a "ServerAlias localhost" may be required to get this working properly.
一些關於 SSH 埠轉送的連結
這取決於所涉及的專案。如果專案相關,且可能會共用資料,那麼最好建立一個儲存庫,並包含多個子目錄,如下所示
$ svnadmin create /repo/svn $ svn mkdir file:///repo/svn/projA $ svn mkdir file:///repo/svn/projB $ svn mkdir file:///repo/svn/projC
如果專案完全無關,且不太可能在它們之間共用資料,那麼最好建立獨立且無關的儲存庫。
$ mkdir /repo/svn $ svnadmin create /repo/svn/projA $ svnadmin create /repo/svn/projB $ svnadmin create /repo/svn/projC
這兩種方法之間的差異如下(由 Ben Collins-Sussman <sussman@collab.net> 解釋)
如果您不在乎保留其中一個儲存庫的所有歷史記錄,則可以只在一個專案的儲存庫下建立一個新目錄,然後匯入另一個專案。
如果您在乎保留兩個專案的歷史記錄,則可以使用「svnadmin dump」將一個儲存庫轉儲,並使用「svnadmin load」將其載入另一個儲存庫。版本號碼會不同,但您仍然會擁有歷史記錄。
Peter Davis <peter@pdavis.cx> 也說明了一種使用 svn 等效於 CVS 模組的方法
只要合併發生在不同的目錄樹中,您就可以使用 svn 版本的 CVS 模組。
在目錄上設定 svn:externals 屬性,以在每次簽出原始目錄時,從其他儲存庫簽出目錄。儲存庫仍然是分開的,但在工作副本中,它們看起來像是已經合併。如果您提交到匯入的目錄,這將會影響外部儲存庫。
合併並不完全乾淨:匯入只會影響工作副本,因此您無法使用第一個儲存庫中的 URL 來存取從第二個儲存庫匯入的模組。它們仍然是分開的 URL。
網路上也有一些有用的工具,可以在合併多個儲存庫時選擇和重新排序版本。例如,svn-merge-repos.pl perl 腳本用於基本操作,而 SvnDumpTool python 類別用於進階重新組織。
如果您使用的是 FSFS 儲存庫後端(從 Subversion 1.2 開始就是預設值),那麼將儲存庫儲存在現代的 NFS 伺服器上(也就是支援鎖定的伺服器)應該是沒問題的。
如果您使用的是具有 Berkeley DB 後端 的儲存庫(使用 Subversion 1.0 和 1.1 建立的儲存庫的預設值,之後不再是預設值),我們建議不要將儲存庫儲存在遠端檔案系統(例如 NFS)上。雖然 Berkeley DB 資料庫和日誌檔可以儲存在遠端檔案系統上,但 Berkeley DB 共享區域檔無法儲存在遠端檔案系統上,因此只有單一檔案系統用戶端可以安全地存取儲存庫,而且甚至連那個用戶端都無法使用所有 Subversion 功能。
工作副本可以儲存在 NFS 上(一個常見的場景是您的家目錄在 NFS 伺服器上)。在 Linux NFS 伺服器上,由於 Subversion 在簽出檔案時內部使用大量的重新命名,一些使用者回報「子樹檢查」應該停用(預設為啟用)。請參閱 NFS Howto 伺服器指南 和 exports(5) 以取得更多關於如何停用子樹檢查的資訊。
我們曾收到至少一份回報,指出工作副本在透過 SMB 存取後發生卡住。問題伺服器執行的是相當舊版的 Samba(2.2.7a)。問題沒有在較新的 Samba(3.0.6)中再次發生。
嘗試讓存取儲存庫的使用者數目盡量少。例如,以特定使用者身分執行 apache 或「svnserve -d」,並讓該使用者完全擁有儲存庫。不要允許任何其他使用者透過 file:/// 網址存取儲存庫,並務必僅以擁有儲存庫的使用者身分執行「svnlook」和「svnadmin」。
如果您的客戶端透過 file:/// 或 svn+ssh:// 存取,則無法避免多個使用者存取。在這種情況下,請閱讀 第 6 章的最後一節,並特別注意底部的「檢查清單」側邊欄。它概述了多項步驟,讓這個場景更安全。
SELinux / Fedora Core 3+ / Red Hat Enterprise 使用者注意事項除了常規的 Unix 權限外,在 SELinux 下,每個檔案、目錄、程序等都有一個「安全性內容」。當一個程序嘗試存取一個檔案時,除了檢查 Unix 權限外,系統還會檢查程序的安全性內容是否與檔案的安全性內容相容。
Fedora Core 3 等系統預設安裝 SELinux,並將 Apache 設定為在相當受限的安全環境中執行。要在 Apache 中執行 Subversion,您必須設定儲存庫的安全環境,以允許 Apache 存取(或停用 Apache 的限制,如果您認為這太過頭)。chcon 指令用於設定檔案的安全環境(類似於 chmod 設定傳統 Unix 權限的方式)。例如,一位使用者必須執行此指令
$ chcon -R -h -t httpd_sys_content_t PATH_TO_REPOSITORY
才能設定安全環境,以順利存取儲存庫。
在特殊情況下,您可能想要銷毀檔案或提交的所有證據。(也許有人不小心提交了機密文件。)這不容易,因為 Subversion 是經過特別設計,絕不遺失資訊。版本是不可變的樹狀結構,彼此建立在彼此之上。從歷程記錄中移除版本會造成骨牌效應,在所有後續版本中造成混亂,並可能使所有工作副本無效。
不過,這個專案計畫未來實作 svnadmin obliterate 指令,用於永久刪除資訊。(請參閱 問題 516。)
在此同時,您唯一的方法是 svnadmin dump 儲存庫,然後將 dumpfile 透過 svndumpfilter(排除不良路徑)傳遞到 svnadmin load 指令。請參閱 Subversion 書籍的 第 5 章,以取得相關詳細資訊。
另一種方法是在設定 基於路徑的授權規則後,使用 svnsync 複製儲存庫,拒絕讀取存取權給任何需要從歷程記錄中篩選的路徑。與 svndumpfilter 不同,svnsync 會自動將來源路徑不可讀取的複製作業轉換為一般新增,如果需要篩選包含複製作業的歷程記錄,這會很有用。
記錄訊息會儲存在存放庫中,作為附加到每個版本的屬性。預設情況下,記錄訊息屬性 (svn:log) 一經提交即無法編輯。這是因為變更 版本屬性 (其中一個為 svn:log) 會導致屬性的前一個值永久丟棄,而 Subversion 會試圖防止您意外執行此操作。不過,有幾種方法可以讓 Subversion 變更版本屬性。
第一種方法是讓存放庫管理員啟用版本屬性修改。這是透過建立稱為「pre-revprop-change」的掛勾來完成的 (有關如何執行此操作的詳細資訊,請參閱 Subversion 書籍中的 此區段)。「pre-revprop-change」掛勾可以在變更前存取舊的記錄訊息,因此它可以透過某種方式保留訊息 (例如,透過傳送電子郵件)。一旦啟用版本屬性修改,您可以透過將 --revprop 開關傳遞給 svn propedit 或 svn propset 來變更版本的記錄訊息,如下列任一範例所示
$ svn propedit -r N --revprop svn:log URL $ svn propset -r N --revprop svn:log "new log message" URL
其中 N 是您想變更其記錄訊息的版本號碼,而 URL 是存放庫的位置。如果您從工作副本中執行此命令,則可以省略 URL。
變更記錄訊息的第二種方法是使用 svnadmin setlog。這必須透過參照檔案系統中存放庫的位置來完成。您無法使用此命令修改遠端存放庫。
$ svnadmin setlog REPOS_PATH -r N FILE
其中 REPOS_PATH 是存放庫位置,N 是您想變更其記錄訊息的版本號碼,而 FILE 是包含新記錄訊息的檔案。如果「pre-revprop-change」掛勾未就緒 (或您想基於某種原因略過掛勾指令碼),您也可以使用 --bypass-hooks 選項。不過,如果您決定使用此選項,請務必小心。您可能會略過變更的電子郵件通知或追蹤版本屬性的備份系統等事項。
首先,請閱讀 Subversion 社群指南。
在消化完指南後,請寄送一封郵件到開發人員清單,在主旨中加上 [PATCH] 字樣和一行描述,並將程式碼補丁內嵌在郵件中(除非您的郵件使用者代理程式會將其完全搞亂)。然後,提交者會接收您的郵件,套用程式碼補丁(進行必要的格式或內容變更),並將其簽入。
基本流程如下:
$ svn co https://svn.apache.org/repos/asf/subversion/site subversion-site $ cd subversion-site/publish [ make changes to faq.html ] $ svn diff faq.html > /tmp/foo $ Mail -s "[PATCH] FAQ updates" < /tmp/foo
當然,您寄送的電子郵件應包含對程式碼補丁功能的詳細說明,如 Subversion 社群指南 所述,但您已經知道這一點,因為您在實際修改程式碼之前就已經閱讀並完全理解指南,對吧? :)
正在尋找事情做嗎?請查看我們的 構想頁面。
例如,假設您想要將 /etc 的部分內容置於儲存庫內的版本控制中
# svn mkdir file:///root/svn-repository/etc \ -m "Make a directory in the repository to correspond to /etc" # cd /etc # svn checkout file:///root/svn-repository/etc ./ # svn add apache samba alsa X11 # svn commit -m "Initial version of my config files"
這利用了 svn checkout 一個不立即顯而易見的功能:您可以直接從儲存庫中簽出目錄到現有目錄。在此,我們首先在儲存庫中建立一個新的空目錄,然後將其簽出到 /etc,將 /etc 轉換為工作副本。完成後,您可以使用正常的 svn add 指令來選擇要新增到儲存庫的檔案和子樹。
如果要匯入目錄的全部內容,而不是內容的子集,可以使用較短的命令序列來執行匯入,然後將目錄轉換為 Subversion 工作副本
# cd /etc # svn import file:///root/svn-repository/etc # svn checkout --force file:///root/svn-repository/etc .
已提交一個問題,以增強 svn import,使其能夠自動將匯入的樹狀結構轉換為工作副本;請參閱 問題 1328。
在開發過程中,Subversion 的儲存庫資料庫架構偶爾會變更。若要利用新功能,您可能必須傾印並載入儲存庫,以重新建立後端資料庫。然而,大多數 Subversion 升級不會涉及傾印和載入。當需要時,新版本的發行說明和 CHANGES 檔案會載有關於它的顯著公告。如果您沒有看到此類公告,則表示沒有架構變更,也不需要傾印/載入。
傾印/載入的替代方法是使用 svnsync 將儲存庫複製到新的儲存庫中。這會稍微慢一些,但更靈活,並具有一些額外的正規化功能,而傾印/載入(目前)不具備這些功能(svnsync 會動態地將屬性正規化為 LF 行尾,並有一個 --source-prop-encoding 選項,可將它們轉換為 UTF-8,這在較新的儲存庫格式中是必需的 --- 請參閱下文,了解如何使用傾印/載入來處理此問題)。
注意:傾印/載入和 svnsync 都只涵蓋儲存庫資料庫,而不涵蓋儲存庫掛勾指令碼、組態檔案和鎖定。這些需要從來源手動複製到目標(請參閱下文中的「複雜程序」)。如果您需要複製完整的儲存庫,而不重新建置後端資料庫,svnadmin hotcopy 可能是更好的選擇。
對於負擔得起一些停機時間的小型儲存庫,這是一個從 Subversion 版本 X 升級到 Y 的簡單傾印/載入程序(請參閱下文,了解針對停機時間最少的較大型儲存庫的更複雜程序)
對於較大的儲存庫,若要將維護時間縮到最短,可以使用稍為複雜的程序。訣竅是將資料傾印並載入至新位置,同時舊儲存庫仍可存取(用於簽出和提交)。完成後(可能需要數小時,甚至數天、數週),請記下已載入的最後版次(或使用「svnlook youngest newrepos」檢查版次號碼),然後開始另一個傾印並載入,其中使用「--incremental -rNEXTREV:HEAD」傾印(NEXTREV 是需要傾印的下一版次)。只要舊儲存庫保持開放,便可重複此步驟 ... 最後,讓原始儲存庫無法存取幾分鐘,同時啟用新儲存庫(注意事項:若將新儲存庫移至與舊儲存庫相同的磁碟位置,且使用 Apache httpd 提供服務,請務必重新啟動 httpd 以重設其快取)。
提示:對於大型儲存庫,我強烈建議在非常快速的儲存空間上建置新儲存庫(「svnadmin load」的目標),如果可能,甚至使用 ramdisk,並在快速儲存空間上執行「svnadmin pack」(然後複製至最終磁碟)。目前「svnadmin load」部分非常耗時(這在 svn 1.10 中可能會大幅改善,因為「svnadmin load」有 --no-flush-to-disk 選項)。
您的指令看起來會像以下
一些需要注意的事項
svnadmin: E125005: Invalid property value found in dumpstream; consider repairing the source or using --bypass-prop-validation while loading. svnadmin: E125005: Cannot accept non-LF line endings in 'svn:log' property這表示版本中的 svn:log 訊息具有非 LF 行尾(舊伺服器接受這些,但 Subversion 1.6 之後不再接受)。您可以透過在「svnadmin load」指令中加入 --bypass-prop-validation 來忽略此輕微損毀(您隨時可以在新儲存庫中 修復 此問題)。或者,您可以在執行傾印和載入之前嘗試在原始儲存庫中 修復 此問題(由於 svn:log 是版本屬性,因此可以輕易修復,而不需「重寫歷史記錄」)。
svnadmin: E125005: Invalid property value found in dumpstream; consider repairing the source or using --bypass-prop-validation while loading. svnadmin: E125005: Cannot accept non-LF line endings in 'svn:ignore' property這比較難修復,因為「svn:ignore」並非修訂屬性(不像 svn:log,可以用 svnadmin setrevprop 處理),而是一個版本化屬性(因此是歷史的一部分)。同樣地,你可以用 --bypass-prop-validation 忽略它。但是,由於這是「歷史中的」損毀,因此只能用傾印加載來修復,所以這可能是嘗試修復的好時機(否則你以後還會再遇到這個問題)。你可以使用像 svndumptool 這樣的工具來修復。但它只能用於傾印檔案,不能用於管道的一部分。因此,一種可能的方法是:將那個單一的(損毀的)修訂傾印到一個檔案,修復它(「svndumptool.py eolfix-prop svn:ignore svn.dump svn.dump.repaired」),載入那個單一的傾印檔,然後使用一個新的「管道」命令繼續(就像上面的步驟 (6))。
請參閱 Subversion 手冊的這一部分,以瞭解傾印和載入的更多詳細資訊。
這個錯誤表示傾印檔 / 傾印串流中修訂的 svn:log 訊息有非 LF 行尾(舊伺服器接受這些行尾,但 Subversion 1.6 之後就不再接受了)。你可以透過在「svnadmin load」命令中加入 --bypass-prop-validation 來忽略載入到新儲存庫中的這個小損毀(你以後隨時可以在新儲存庫中修復它)。或者,你可以在執行傾印加載之前嘗試在原始儲存庫中修復它(因為 svn:log 是修訂屬性,所以可以輕鬆修復它,而不用「重寫歷史」)。另外請注意,svnsync 會動態正規化這個屬性,因此它可能比傾印加載更簡單。
沒有正規化 svn:log 屬性中行尾的標準程序,但可以使用管理命令「svnlook propget」、「svnlook log」和「svnadmin setlog」來完成。
你可以將它們縫合到腳本中,以處理儲存庫中的所有版本,就像在這些 bash 一行指令中一樣
Find the "broken" revisions and echo the revision numbers: bash$ YOUNGEST=`svnlook youngest $REPOS`; for (( i=1; i<=$YOUNGEST; i++ )); \ do svnlook propget -r $i --revprop $REPOS svn:log | xxd -ps -c1 | fgrep '0d' > /dev/null \ && echo "$i" ; done; echo "Verified until revision $YOUNGEST"
Find and immediately fix the "broken" revisions with 'svnadmin setlog': bash$ YOUNGEST=`svnlook youngest $REPOS`; for (( i=1; i<=$YOUNGEST; i++ )); \ do svnlook propget -r $i --revprop $REPOS svn:log | xxd -ps -c1 | fgrep '0d' > /dev/null \ && echo "Fixing r$i" && svnadmin setlog $REPOS --bypass-hooks -r$i \ <( svnlook log -r$i $REPOS | sed '$d' ); done; echo "Verified until revision $YOUNGEST" (the "sed '$d'" strips off the extra newline that's added by "svnlook log")
此常見問題解答條目自 2003 年起便未更新,且已知包含不再準確或相關的資訊。
TortoiseSVN 有一份說明如何在 Windows 上設定 Subversion 伺服器的優秀文件。前往 https://tortoisesvn.dev.org.tw/docs/release/TortoiseSVN_en/tsvn-serversetup.html#tsvn-serversetup-apache-5,查看有關 SSPI 驗證的區段。
設定中的一個重要部分是這行
SSPIOfferBasic On
沒有這行,支援 SSPI 的瀏覽器會提示輸入使用者的憑證,但像 Subversion 這樣不支援 SSPI 的客戶端不會提示輸入。(Neon 的目前版本 - Subversion 的 HTTP 函式庫 - 只處理基本驗證。)由於客戶端從未要求輸入憑證,因此任何需要驗證的動作都會失敗。加入這行會告訴 mod_auth_sspi 使用基本驗證與客戶端,但使用 Windows 網域控制器來驗證憑證。
我們建議你盡可能使用「.svn」。不過,如果你在 Windows 上使用 Visual Studio 2002 或 2003,你可能需要設定環境變數 SVN_ASP_DOT_NET_HACK,如 此處 所述。
或者,您可以為管理目錄使用一個完全自訂的名稱。我們不建議這麼做,因為您的工作副本可能無法與您自訂的 Subversion 以外的其他用戶端一起使用。不過,如果您真的必須這麼做,只要將 subversion/include/svn_wc.h 中的這行從
#define SVN_WC_ADM_DIR_NAME ".svn"
變更為(例如)
#define SVN_WC_ADM_DIR_NAME "SVN"
然後重新編譯您的用戶端。
這個問題會在兩種情況下發生。如果您在檔案系統不區分大小寫的操作系統(例如 Windows)上新增檔案,您可能會發現您不小心新增了一個檔案名稱大小寫錯誤的檔案。或者,您可能只是決定變更儲存庫中現有檔案的大小寫。
如果您使用的是區分大小寫的檔案系統,這完全不是問題。只要將檔案移至新名稱即可,例如,
svn mv file.java File.java
從 Subversion 1.7 開始,這也適用於 Windows,即使它使用的是不區分大小寫的檔案系統。
如果您在 Windows 上使用 Subversion 1.6 或更舊版本,或者您在 Windows 以外的操作系統上使用不區分大小寫的檔案系統,這個技術將無法使用。在這種情況下,您可以透過將檔案複製到某個暫時位置、從 Subversion 中刪除檔案,然後新增大小寫正確的副本來達成這個目的。或者,一個更好的方法是使用 Subversion URL 執行移動操作。建議使用 URL,因為它會保留檔案的歷程記錄,而且會立即生效。
不過,這兩種方法都會讓 Windows 工作副本出現問題,因為 Windows 在嘗試更新有衝突的文件名稱時仍然可能會混淆。(您會收到類似 svn: Failed to add file 'File.java': object of the same name already exists 的訊息)。解決問題的方法之一是刪除您的工作副本,然後再次簽出。如果您不想要這樣做,您必須執行兩步驟更新。
對於每個大小寫錯誤的文件,以下指令會變更大小寫
svn mv svn://svnserver/path/to/file.java svn://svnserver/path/to/File.java
若要更新工作副本,請變更至相關目錄並執行
svn update file.java svn update
第一次更新會從您的工作副本中移除 file.java,第二次更新會加入 File.java,讓您擁有正確的工作副本。或者,如果您有許多有問題的文件,您可以用這種方式更新工作副本
svn update * svn update
如您所見,在檔案系統不區分大小寫的操作系統中,加入大小寫錯誤的文件很難修正。請在第一次加入文件時就盡量正確!若要從一開始就避免問題發生,您可以建立一個呼叫文件 check-case-insensitive.pl 的提交前掛勾。該文件位於 Subversion 原始碼 tarball 中的目錄 contrib/hook-scripts。
如下所示,可以在不記住一個修訂編號的情況下,從分支合併到主幹。或反之亦然(範例中未顯示)。
以下範例假設在 /home/repos 中有一個現有的儲存庫,您想要在其中啟動一個名為 bar 的分支,其中包含一個您將編輯的名為 foo 的文件。
為了追蹤分支合併,此儲存庫已設定 tags/branch_traces/ 來保留標籤。
# setup branch and tags $ svn copy file:///home/repos/trunk \ file:///home/repos/branches/bar_branch \ -m "start of bar branch" $ svn copy file:///home/repos/branches/bar_branch \ file:///home/repos/tags/branch_traces/bar_last_merge \ -m "start" # checkout branch working copy $ svn checkout file:///home/repos/branches/bar_branch wc $ cd wc # edit foo.txt file and commit $ echo "some text" >>foo.txt $ svn commit -m "edited foo" # switch to trunk and merge changes from branch $ svn switch file:///home/repos/trunk $ svn merge file:///home/repos/tags/branch_traces/bar_last_merge \ file:///home/repos/branches/bar_branch # Now check the file content of 'foo.txt', it should contain the changes. # commit the merge $ svn commit -m "Merge change X from bar_branch." # finally, update the trace branch to reflect the new state of things $ svn delete -m "Remove old trace branch in preparation for refresh." \ file:///home/repos/tags/branch_traces/bar_last_merge $ svn copy file:///home/repos/branches/bar_branch \ file:///home/repos/tags/branch_traces/bar_last_merge \ -m "Reflect merge of change X."
Subversion 會遞增整個儲存庫的版本號碼,因此它無法將任何關鍵字擴充為該號碼 - 它必須在每次更新和提交時搜尋並修改工作副本中的每個檔案。
您要的資訊(工作副本的版本)可透過命令 svnversion 取得;它會提供給您工作副本版本層級的資訊(請參閱 svnversion --help 以取得詳細資料)。
您可以將它納入您的建置或發行程序,以取得您需要的資訊並放入來源本身。例如,在基於 GNU make 的建置環境中,將 類似這樣的內容 加入您的 Makefile
## ## To use this, in yourfile.c do something like this: ## printf("this program was compiled from SVN revision %s\n",SVN_REV); ## SVNDEF := -D'SVN_REV="$(shell svnversion -n .)"' CFLAGS := $(SVNDEF) ... continue with your other flags ...
(請注意,這在非 GNU 版本的 make 中無法運作。如果您的建置程序需要可攜式,請勿使用它。)
或嘗試此配方
## ## on every build, record the working copy revision string ## svn_version.c: FORCE echo -n 'const char* svn_version(void) { const char* SVN_Version = "' \ > svn_version.c svnversion -n . >> svn_version.c echo '"; return SVN_Version; }' >> svn_version.c ## ## Then any executable that links in svn_version.o will be able ## to call the function svn_version() to get a string that ## describes exactly what revision was built. ##
Windows 使用者可能想要使用 SubWCRev.exe,可從 TortoiseSVN 下載頁面 取得;它會將給定檔案中的所有 $WCREV$ 標籤替換為目前的工作副本版本。
另一種替代方案是為 'svn commit' 建立一個包裝器,它會在提交前自動替換檔案中的內容(但請小心不要搞亂檔案 - 在提交前靜默地處理檔案對使用者來說可能會很可怕)。這樣您就可以注入您要的任何元資料(而且它會與檔案的常規內容一起提交到儲存庫中)。
沒有。CVS 中的 $Log$ 關鍵字沒有等效項。如果您想要擷取特定檔案的記錄,您可以執行 'svn log your-file-name' 或 'svn log url-to-your-file'。從郵件清單中說明了為何 $Log$ 不好的原因
"$Log$ is a total horror the moment you start merging changes between branches. You're practically guaranteed to get conflicts there, which -- because of the nature of this keyword -- simply cannot be resolved automatically."
而且
Subversion log messages are mutable, they can be changed by setting the svn:log revision property. So the expansion of $Log:$ in any given file could be out of date. Update may well need to retrieve the appropriate log message for each occurrence of the $Log:$ keyword, even if the file that contained it was not otherwise updated.
我不在乎。無論如何,我都想使用它。你會實作它嗎?
不會。我們沒有計畫自行實作或接受實作此功能的修補程式。如果你想散布包含某種變更日誌的檔案,你或許可以在你的建置系統中解決此限制。
答案是:不要將該檔案置於版本控制之下。相反地,將該檔案的範本置於版本控制之下,例如「file.tmpl」。
然後,在初始「svn checkout」之後,讓你的使用者(或你的建置系統)將範本的正常 OS 複製到正確的檔名,並讓使用者自訂複製。該檔案未經過版本控制,因此永遠不會提交。如果你願意,你可以將該檔案新增至其父目錄的 svn:ignore 屬性,這樣它就不會在「svn status」指令中顯示為「?」。
ssh 有自己的密碼和自己的驗證快取機制。它的驗證快取是 Subversion 的外部,而且必須獨立於 Subversion 設定。
OpenSSH 包含 ssh-keygen 以建立金鑰、ssh-agent 以快取密碼,以及 ssh-add 以將密碼新增至代理快取。一個簡化 ssh-agent 使用的熱門指令碼是 keychain。在 Windows 上,PuTTY 是熱門的替代 ssh 客戶端;請參閱 PuTTYgen 以匯入 OpenSSH 金鑰,以及 pageant 以快取密碼。
設定 ssh-agent 超出本文檔的範圍,但 Google 搜尋「ssh-agent」 將會快速提供您答案。
注意:這一切假設您使用的是 OpenSSH。還有其他 ssh 實作,而且假設它們會允許您執行類似的事情,但我們目前還不知道詳細資訊。
您已嘗試修改他們的各種登入檔案,例如 .bash_profile,但都沒有用!這是因為當 Subversion 呼叫它時,ssh 會忽略這些檔案。但不需要修改 PATH;相反地,您可以直接提供 ssh svnserve 命令的全名。以下是如何執行
對於需要 svn+ssh 存取權的每個使用者,產生一組新的 ssh 公開金鑰對,他們將僅用於 Subversion,而不是用於一般登入。請他們為金鑰對取一個有特色的名稱,例如 ~/.ssh/id_dsa.subversion。將金鑰的公開部分新增到伺服器電腦上的 ~/.ssh/authorized_keys 檔案,首先在 ssh-rsa 或 ssh-dss 字詞前的行開頭插入一點魔法,如下所示
之前 |
---|
ssh-dss AAAAB3Nblahblahblahblah |
之後 |
command="/opt/subversion/bin/svnserve -t" ssh-dss AAAAB3Nblahblahblahblah |
顯然地,將 /opt/subversion/bin/svnserve 替換為適合您系統的任何內容。您可能還想在命令中指定 Subversion 儲存庫的完整路徑(透過使用 -r 選項),以節省您的使用者一些輸入。
即使您的使用者嘗試執行其他指令,command= 魔術會導致遠端機器上的 sshd 呼叫 svnserve。請參閱 sshd(8) 手冊頁(AUTHORIZED_KEYS 檔案格式 章節)以取得詳細資料。
現在,當您的使用者執行 Subversion 伺服器時,請確定他們有一個 SVN_SSH 環境變數,該變數「指向」其金鑰對的私密部分,方法如下(適用於 Bourne Again shell):
SVN_SSH="ssh -i $HOME/.ssh/id_dsa.subversion" export SVN_SSH
此檔案 更詳細地討論此主題。
請參閱 此其他問題 的解答中關於破解 ~/.ssh/authorized_keys 檔案的區段;忽略關於在 PATH 中取得 svnserve 的內容。
Subversion 預設不會變更檔案內容;您必須刻意設定檔案上的 svn:eol-style 或 svn:keywords 屬性才能執行此動作。這使得 Subversion 比 CVS 的預設行為安全許多,但此安全性帶來了一些不便。
回答第一個問題:若要設定儲存庫中所有檔案的屬性,您需要用困難的方式執行。您能做的就是對每個檔案(在工作副本中)執行 svn propset,然後 svn commit。指令碼可能會對您有所幫助。
但未來的檔案呢?很遺憾地,伺服器機制無法自動設定提交檔案的屬性。這表示所有使用者在執行 svn add 加入檔案時,都必須記得設定特定屬性。很幸運地,有一個用戶端工具可以協助處理這項工作。請參閱書中的 auto-props 功能。您需要確定所有使用者都適當地設定其用戶端 auto-props 設定。
您可以撰寫一個提交前掛勾指令碼,以拒絕任何忘記新增屬性至新檔案的提交(例如,請參閱 https://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/check-mime-type.pl)。不過,這種方法可能會過於繁瑣。例如,如果有人忘記設定 svn:eol-style,那麼當其他人使用不同的作業系統開啟檔案時,就會立即發現。一旦發現,很容易就能修正:只要設定屬性並提交即可。
注意:許多使用者要求提供一個功能,讓伺服器自動「廣播」執行時間設定至用戶端,例如 auto-props 設定。已經有人針對此功能提出功能要求(問題 1974),不過開發人員仍在討論此功能,尚未開始進行。
Subversion 命令列用戶端會呼叫環境變數 SVN_EDITOR 中定義的編輯器。這個環境變數會連同用於輸入/編輯記錄訊息的暫時檔案名稱,直接傳遞至作業系統。
由於 SVN_EDITOR 字串會原樣傳遞至系統的命令殼層,因此編輯器名稱或編輯器路徑名稱中的空白,除非編輯器名稱加上引號,否則無法使用。
例如,如果 Windows 中的編輯器位於 C:\Program Files\Posix Tools\bin\vi
,您會希望將變數設定如下
set SVN_EDITOR="C:\Program Files\Posix Tools\bin\vi"
請注意,Windows shell 中不需要跳脫引號,因為它們並非 set
指令的語法的一部分。
在 UNIX 系統中,您需要遵循 shell 的特定方法來設定變數。例如,在 bash shell 中,下列指令應可運作
SVN_EDITOR='"/usr/local/more editors/bin/xemacs"' export SVN_EDITOR
如果編輯器的呼叫需要命令列選項,請在 SVN_EDITOR 環境變數中的編輯器名稱後面加上該選項,就像您在命令列中使用的方式一樣。例如,如果上述編輯器需要選項 -nx -r
,下列指令將提供這些選項
適用於 Windows
set SVN_EDITOR="C:\Program Files\Posix Tools\bin\vi" -nx -r
適用於 UNIX/bash
SVN_EDITOR='"/usr/local/more editors/bin/xemacs" -nx -r' export SVN_EDITOR
請注意,SVN_EDITOR 是 Subversion 特有的環境變數設定,用於編輯器選取。Subversion 也支援使用更通用的 EDITOR 變數,但如果您需要 Subversion 的特殊行為,最好使用 SVN_EDITOR 變數。
這項工作一直都在進行,而且只要在您的存放庫中新增提交後掛鉤指令碼,就能輕鬆達成。在本書的 第 5 章 中閱讀有關掛鉤指令碼的資訊。基本概念是讓「實時網站」只是一個普通的作業副本,然後讓您的提交後掛鉤指令碼在其中執行「svn update」。
實際上,有幾件事需要注意。執行提交的伺服器程式 (svnserve 或 apache) 與執行提交後掛鉤指令碼的程式相同。這表示此程式必須具有適當的權限才能更新作業副本。換句話說,作業副本必須由與 svnserve 或 apache 相同的使用者擁有 - 或至少作業副本必須設定適當的權限。
如果伺服器需要更新它不擁有的工作副本(例如,使用者 joe 的 ~/public_html/ 區域),一種方法是建立一個 +s 二進位程式來執行更新,因為 Unix 不允許指令碼執行 +s。編譯一個微小的 C 程式
#include <stddef.h> #include <stdlib.h> #include <unistd.h> int main(void) { execl("/usr/local/bin/svn", "svn", "update", "/home/joe/public_html/", (const char *) NULL); return(EXIT_FAILURE); }
... 然後 chmod +s 二進位程式,並確保它由使用者 'joe' 擁有。然後在提交後掛鉤中,新增一行來執行二進位程式。
如果您在讓掛鉤運作時遇到問題,請參閱 "我的儲存庫掛鉤為何無法運作?"。
此外,您可能希望防止 apache 匯出實際工作副本中的 .svn/ 目錄。將此新增至您的 httpd.conf
# Disallow browsing of Subversion working copy administrative dirs. <DirectoryMatch "^/.*/\.svn/"> Order deny,allow Deny from all </DirectoryMatch>
最後,如果要更新的工作副本與 Subversion 伺服器不在同一台機器上,svnpubsub 可用於 Subversion 伺服器,以向 Web 伺服器上的監聽 svnwcsub 客戶端宣告提交。
Subversion 不支援檢出單一檔案,它只支援檢出目錄結構。
但是,您可以使用 'svn export' 來匯出單一檔案。這將擷取檔案的內容,它只是不會建立版本化的工作副本。
您無法。嘗試這樣做是個壞主意。
工作副本的基本設計有兩個規則:(1) 隨意編輯檔案,以及 (2) 使用 Subversion 客戶端進行任何樹狀結構變更(新增、刪除、移動、複製)。如果遵循這些規則,客戶端可以成功管理工作副本。如果在 Subversion 外部發生重新命名或其他重新排列,則表示已違反使用者介面,而工作副本可能會損毀。客戶端無法猜測發生了什麼事。
人們有時會遇到這個問題,因為他們想要讓版本控制「透明化」。他們誘騙使用者使用工作副本,然後執行一個腳本,試著猜測發生了什麼事,並執行適當的客戶端指令。不幸的是,這個技術只能走一小段距離。'svn status' 會顯示遺失的項目和未版本化的項目,腳本接著可以自動執行 'svn rm' 或 'svn add'。但是如果發生了移動或複製,你就倒楣了。即使腳本有萬無一失的方法來偵測這些事情,'svn mv' 和 'svn cp' 也無法在動作發生後執行。
總之:工作副本完全在 Subversion 的控制之下,而 Subversion 並非設計成透明的。如果你正在尋找透明化,請嘗試設定一個 apache 伺服器,並使用本書附錄 C 中所述的「SVNAutoversioning」功能。這將允許使用者將儲存庫掛載為網路磁碟,對磁碟區所做的任何變更都會導致伺服器上自動提交。
有三個步驟
假設你有一個儲存庫 /svn/myrepos,它使用 BDB 後端,而你想要切換到使用 FSFS 後端
一旦您對新的儲存庫感到滿意,請刪除舊的儲存庫。
若要執行相反的動作,並從 FSFS 遷移到 BDB,請變更 svnadmin create 指令以指定 BDB。
當您第一次將檔案新增或匯入到 Subversion 中時,系統會檢查檔案以確定它是否為二進位檔案。目前,Subversion 只會檢視檔案的前 1024 個位元組;如果任何一個位元組為零,或者超過 15% 不是 ASCII 可列印字元,則 Subversion 會將檔案稱為二進位檔案。
如果 Subversion 判斷檔案是二進位,檔案會收到一個 svn:mime-type 屬性,設定為「application/octet-stream」。(您隨時可以使用 自動屬性功能 或使用 svn propset 手動設定屬性來覆寫此設定。)
Subversion 1.7 和更新版本可以選擇編譯,支援 libmagic,以偵測加入版本控制的二進位檔案的 MIME 類型。此功能僅用於未透過自動屬性或 mime-types-file 組態選項找到 MIME 類型的二進位檔案。如果 libmagic 識別檔案為文字檔案,Subversion 預設會將檔案視為文字檔案。
Subversion 將下列檔案視為文字
所有其他檔案都視為二進位,表示 Subversion 會
在其他所有方面,Subversion 將二進位檔案視為與文字檔案相同,例如,如果您設定 svn:keywords 或 svn:eol-style 屬性,Subversion 會對二進位檔案執行關鍵字替換或換行符號轉換。
請注意,檔案是否為二進位檔案不會影響用於儲存檔案變更的儲存庫空間量,也不會影響用戶端和伺服器之間的流量量。對於儲存和傳輸目的,Subversion 使用在二進位檔案和文字檔案上都能正常運作的差異化方法;這與「svn diff」指令使用的差異化方法完全無關。
svn diff 沒有選項可以執行此操作,但
svn log -vq -r10就能完全符合您的需求;
svn log -vq -r123:456 | egrep '^ {3}[ADMR] ' | cut -c6- | sort | uniq
您想執行類似下列動作
svn mv svn://server/trunk/stuff/* svn://server/trunk/some-other-dir
但會失敗,並顯示
svn: Path 'svn://server/trunk/stuff/*' does not exist in revision 123
... 或其他難以理解的錯誤訊息。
Subversion 沒有擴充 URL 引數中的萬用字元,例如「*」。 (技術上來說,Subversion 也不會擴充本地路徑中的萬用字元,但在大多數作業系統中,shell 會在將產生的清單傳遞給 Subversion 之前,先擴充命令列中本地路徑中的萬用字元。)
您必須自行產生來源 URL 清單。您可以使用下列方式(在 Bash 中)執行此動作
s=svn://server/trunk/stuff items=$(svn ls "$s") urls=$(for item in $items; do echo $s/$item; done) svn mv $urls svn://server/trunk/some-other-dir -m "Moved all at once"
在 Subversion v1.4 及更早版本中,Subversion 不允許您在一個命令中「cp」和「mv」多個路徑或 URL。您必須發出多個命令。如果您碰巧有一個工作副本,其中包含所有來源檔案以及目標目錄,則可以利用 shell 的萬用字元功能執行移動,如下所示(針對 Bash)
for i in stuff/*; do svn mv $i some-other-dir; done svn ci -m "moved all the stuff into some other dir"
在任何情況下,您都可以隨時累積來源檔案名稱的清單,然後對清單中的每個項目執行「svn mv」,如下所示
s=svn://server/trunk/stuff svn ls "$s" | \ while read f do svn mv "$s/$f" svn://server/trunk/some-other-dir -m "Moved just one file" done
不過請注意,這會為每個來源檔案產生一個提交;這與上述方法(使用工作副本)形成對比,後者只會產生一個提交總計。
有一個稱為「svnmucc」(以前稱為「mucc」)的程式,其來源與 Subversion 一起發行,讓您可以將多個命令合併為一個提交。請參閱工具和貢獻頁面。
人們經常想使用 Subversion 追蹤他們對第三方程式碼的本地變更,即使跨越第三方升級,也就是說,他們想維護自己的分歧分支,同時仍然納入上游來源的新版本。這通常稱為供應商分支(此術語早於 Subversion),而維護 Subversion 中一個分支的技術在此處說明。
如果供應商程式碼是託管在遠端 Subversion 儲存庫中,則您可以使用 Piston 來管理您的供應商程式碼副本。
使用「svn merge」或「svn copy」,如 Subversion 書籍中所述。
您的工作副本並未毀損,您的資料也未遺失。Subversion 的工作副本是一個記錄系統,表示它會在執行任何動作之前記錄所有即將執行的動作。如果 svn 客戶端程式突然中斷(分段錯誤或終止,而不是使用 Control-C),則會留下一個或多個鎖定檔,以及描述未完成工作的記錄檔。(「svn status」命令會在鎖定的目錄旁邊顯示「L」。)任何嘗試存取工作副本的其他程序,在看到鎖定時都會失敗。若要喚醒您的工作副本,您需要告訴 svn 客戶端完成工作。只需執行
svn cleanup working-copy
會造成此問題的三種情況
失敗提交的殘留檔案散落在您的工作副本中。
您可能在伺服器新增新版次和您的用戶端執行提交後管理工作(包括更新您的文字基礎副本)之間,發生提交失敗的情況。這可能會因為各種原因發生,包括(很少見)資料庫後端的錯誤或(較常見)在不恰當的時間發生網路中斷。
如果發生這種情況,您可能已經提交了您現在嘗試提交的變更。您可以使用「svn log -rHEAD」查看您假設失敗的提交是否實際上成功。如果成功了,請執行「svn revert」回復您的本機變更,然後執行「svn update」從伺服器取回您自己的變更。(請注意,只有「svn update」會將您的本機副本更新為最新;回復不會執行此動作。)
混合版次。
當 Subversion 提交時,用戶端只會變更提交觸及的節點的版次號碼,而不是工作副本中的所有節點。這表示在單一工作副本中,檔案和子目錄的版次可能不同,這取決於您上次提交它們的時間。在某些作業中(例如目錄屬性修改),如果儲存庫有較新版本的節點,提交將會被拒絕,以防止資料遺失。請參閱 混合版次有其限制 中的 使用 Subversion 進行版本控制 一書,以取得詳細資訊。
您可以透過在工作副本中執行「svn update」來修正此問題。
您可能真正過時了 — 也就是說,您嘗試提交變更到一個檔案,而自從您上次更新該檔案的副本後,該檔案已被其他人變更。同樣地,「svn update」是修正此問題的方法。
為了將你的新檔案包含在修補程式中,你可能執行 svn add 指令,以便 svn diff 指令將新檔案包含在修補程式中。如果你的修補程式提交至程式碼庫,而你執行 svn update,則你可能會收到錯誤訊息:「svn:無法新增檔案 'my.new.file':同名物件已存在」。
你收到此錯誤訊息的原因是你的工作副本中仍有檔案的本機副本。修正此問題的步驟為:
你可能想要將儲存庫中的新檔案與你的原始檔案進行比較。
Subversion 使用外掛程式系統允許存取儲存庫。目前有三個此類外掛程式:ra_local 允許存取本機儲存庫,ra_neon 或 ra_serf 允許透過 WebDAV 存取儲存庫,而 ra_svn 允許透過 svnserve 伺服器進行本機或遠端存取。當你嘗試在 Subversion 中執行作業時,程式會根據 URL 架構嘗試動態載入外掛程式。`file://' URL 會嘗試載入 ra_local,而 `http://' URL 會嘗試載入 ra_neon 或 ra_serf。
您看到的錯誤表示動態連結器/載入器找不到要載入的插件。對於 `http://' 存取,這通常表示您在編譯 Subversion 時未將其連結到 neon 或 serf(請查看組態指令碼輸出和 config.log 檔案以取得相關資訊)。當您使用共用函式庫建置 Subversion,然後嘗試在未先執行「make install」的情況下執行 Subversion 時,也會發生這種情況。另一個可能的原因是您執行了 make install,但函式庫安裝在動態連結器/載入器無法辨識的位置。在 Linux 中,您可以透過將函式庫目錄新增至 /etc/ld.so.conf 並執行 ldconfig,讓連結器/載入器找到函式庫。如果您不希望執行此動作,或者您沒有 root 存取權,您也可以在 LD_LIBRARY_PATH 環境變數中指定函式庫目錄。
您的系統中可能還有 /usr/local/bin/apr-config 和 /usr/local/bin/apu-config 的舊副本。請將它們移除,確認您建置的 apr/ 和 apr-util/ 已完全更新,然後再試一次。
您可能只需要取得最新的平台 SDK。隨附 VC++ 6.0 的 SDK 不夠新。
像這樣
svn import file:///d:/some/path/to/repos/on/d/drive
請參閱 Subversion Repository URLs 以取得更多詳細資訊。
Visual Studio 可以使用 ASP.Net 的 Web 子系統,它使用 FrontPage 伺服器延伸模組透過 IIS 進行遠端發佈。這個子系統會拒絕任何以「.」開頭的路徑名稱。這會造成問題,因為當您嘗試遠端發佈 Subversion 工作副本時,會出現「.svn」子目錄。錯誤訊息會顯示類似「無法讀取專案資訊」的內容。
若要解決這個問題,請將環境變數 SVN_ASP_DOT_NET_HACK 設為任何值,這會指示 Windows 用戶端在您的工作副本中使用「_svn」作為目錄名稱。請參閱 Subversion 1.3 發行說明中的相關區段 以取得更多詳細資訊,並參閱 這個問題 以取得自訂管理目錄名稱的其他方法。
例如,一位使用者回報說匯入在本地端存取時運作良好
$ mkdir test $ touch test/testfile $ svn import test file:///var/svn/test -m "Initial import" Adding test/testfile Transmitting file data . Committed revision 1.但從遠端主機則不行
$ svn import http://svn.sabi.net/test testfile -m "import" nicholas's password: xxxxxxx svn_error: #21110 : <Activity not found> The specified activity does not exist.
當 REPOS/dav/ 目錄無法由 httpd 程序寫入時,我們看過這個問題。請檢查權限以確保 Apache 可以寫入 dav/ 目錄(當然還有 db/)。
簡短的回答:這是為了您自己好。
Subversion 非常重視保護您的資料,而不仅仅是您的版本化資料。您對已版本化檔案所做的修改,以及排定新增至版本控制系統的新檔案,都必須小心處理。
讓 svn revert 指令需要明確的目標,即使該目標只是「.」—這是達成此目的的方法之一。此需求(以及要求您提供 --recursive (-R) 旗標,如果您想要該行為)的用意是讓您真正思考您正在做的事,因為一旦您的檔案還原,您的本地修改將永遠消失。
如果您允許透過 Apache 匿名寫入存儲庫,Apache 伺服器絕不會向 SVN 客戶端索取使用者名稱,而是允許在未驗證的情況下執行寫入操作。由於 Subversion 不知道是誰執行操作,因此會產生類似這樣的記錄
$ svn log ------------------------------------------------------------------------ rev 24: (no author) | 2003-07-29 19:28:35 +0200 (Tue, 29 Jul 2003)
請參閱 Subversion 書籍,以了解如何在 Apache 中設定存取限制。
這些錯誤似乎是由於各種監視檔案系統變更的 Windows 服務(防毒軟體、索引服務、COM+ 事件通知服務)所造成。這並非 Subversion 中的錯誤,因此我們很難修復它。調查的目前狀態摘要可在此處取得 這裡。一個應可為大多數人降低發生率的解決方法已在版本 7598 中實作;如果您有較早的版本,請更新至最新版本。
這通常是因為系統上缺乏可用的熵。您可能需要設定系統從硬碟和網路中斷等來源收集熵。請參閱您的系統手冊頁,特別是 random(4) 和 rndcontrol(8),了解如何進行此變更。
這表示您的 httpd.conf 設定錯誤。通常,當您定義 Subversion 虛擬「位置」時,同時存在於兩個不同的範圍內,就會發生此錯誤。
例如,如果您已將儲存庫匯出為 <Location /www/foo>,但您也將 DocumentRoot 設定為 /www,那麼您就有麻煩了。當請求進入 /www/foo/bar 時,apache 不知道是否要在 DocumentRoot 中找到名為 /foo/bar 的實際檔案,或要求 mod_dav_svn 從 /www/foo 儲存庫中擷取檔案 /bar。通常前者會獲勝,因此會出現「永久搬移」錯誤。
解決方案是確保您的儲存庫 <Location> 不會 重疊或存在於已作為一般 Web 共享匯出的任何區域內。
您在 Web 根目錄中有一個物件與您的儲存庫 URL 同名,這也是可能的。例如,假設您的 Web 伺服器的文件根目錄是 /var/www,而您的 Subversion 儲存庫位於 /home/svn/repo。然後,您將 Apache 設定為在 https://127.0.0.1/myrepo 提供儲存庫服務。如果您接著建立目錄 /var/www/myrepo/,這將導致發生 301 錯誤。
在設定和建置的環境變數 CFLAGS 中加入 -qlanglvl=extended,將使 xlc 更具彈性,而且程式碼應可編譯而不會出錯。請參閱 https://svn.haxx.se/dev/archive-2004-01/0922.shtml 及其相關執行緒,以取得更多詳細資料。
請參閱 問題 695。svn checkout -N 的目前實作相當不穩定。它會產生一個工作副本,其中缺少項目,卻不了解其「不完整」。顯然,許多 CVS 使用者相當依賴此範例,但沒有任何 Subversion 開發人員會這麼做。目前,除了變更您的流程之外,並沒有任何解決方法:嘗試檢出儲存庫的個別子目錄,並手動嵌套您的工作副本。
在此情況下,錯誤訊息有點誤導人。Apache 很可能無法載入 mod_dav_svn.so 所依賴的一個或多個 DLL。如果 Apache 以服務方式執行,它不會與一般使用者擁有相同的 PATH。請確定 libdb4*.dll、intl3_svn.dll、libeay32.dll 和 ssleay32.dll 存在於 \Apache\bin 或 \Apache\modules 中。如果它們不存在,您可以從您的 Subversion 安裝目錄中複製它們。
如果這仍然無法解決問題,您應該對 mod_dav_svn.so 使用類似 Dependency Walker 的工具,以查看是否有任何其他未解決的相依性。
它們應該呼叫外部程式,但呼叫似乎永遠不會發生。
在 Subversion 呼叫掛勾指令碼之前,它會從環境中移除所有變數,包括 Unix 上的 $PATH 和 Windows 上的 %PATH%。因此,您的指令碼只能在您拼寫出該程式的絕對名稱時,才能執行另一個程式。
請確定掛勾指令碼已正確命名:例如,在 Unix 上,提交後掛勾應命名為 post-commit(無副檔名),而在 Windows 上應命名為 post-commit.bat 或 post-commit.exe。
除錯提示
如果您使用 Linux 或 Unix,請嘗試透過下列步驟「手動」執行指令碼
請注意「env」的第一個引數為破折號;這會確保環境為空。$ env - ./post-commit /var/lib/svn-repos 1234
使用外部 diff 指令時,Subversion 會建構相當複雜的命令列。首先是指定的 --diff-cmd。接下來是指定的 --extensions(不過會忽略空的 --extensions),或未指定 --extensions(或指定為 '')時為「-u」。第三和第四,Subversion 會傳遞「-L」和第一個檔案的標籤(例如「project_issues.html(版本 11209)」)。第五和第六是另一個「-L」和第二個標籤。第七和第八是第一個和第二個檔案名稱(例如「.svn/text-base/project_issues.html.svn-base」和「.svn/tmp/project_issues.html.tmp」)。
如果您的偏好 diff 指令不支援這些引數,您可能需要建立一個小型包裝指令碼,以捨棄引數並僅使用最後幾個檔案路徑。
警告:請注意,Subversion 不希望外部 diff 程式變更其接收的檔案,否則可能會打亂工作副本。
如需進一步資訊,請參閱問題 #2044。
為了避免每次伺服器操作都必須輸入密碼,Subversion 可以快取認證資料。
舊版本的 Subversion 可能已快取未加密的密碼(「已納入」),而 Subversion 始終支援讀取這些密碼。Subversion 是否快取新認證資料以及如何快取,取決於多項因素,包括存取方法、作業系統、編譯時選項,以及用戶端執行時期設定檔中的設定。
若要顯示快取中的認證資料,請使用 svn auth。認證資料絕不會自動移除,但可以使用 svn auth --remove 手動移除。
在 Windows 上,Subversion 使用標準 Windows API 加密資料,因此只有使用者可以解密快取的密碼。(自 Subversion 1.2 起)
在 macOS 上,Subversion 使用系統 Keychain 設施加密/儲存使用者的 svn 密碼。(自 Subversion 1.4 起)
在 UNIX/Linux 上,Subversion 支援最多四個認證資料快取
若要確定 Subversion 用戶端支援哪些認證資料快取,請執行 svn --version 命令,並在輸出的尾端尋找「可用下列驗證認證資料快取」。
GNOME Keyring 和 KWallet 都能協助在磁碟上儲存已加密的密碼。Subversion 要支援這些程式(自 Subversion 1.6 起),它們必須在編譯時和執行時都可用。
待辦事項:討論 GPG-Agent。
根據編譯時期選項 (--enable-plaintext-password-storage) 和執行時期設定 (見下方),Subversion 可能會 回退至將密碼儲存在純文字快取中。
--enable-plaintext-password-storage 的預設值在 Subversion 1.12 中已從 True 變更為 False,因此除非明確啟用,否則會停用純文字快取。
包含快取純文字密碼的目錄 (通常為 ~/.subversion/auth/) 具有 700 的權限,表示只有使用者 (和 root) 可以讀取。
以下選項可在您的執行時期設定檔中使用 (每個使用者 ~/.subversion/config 和 ~/.subversion/servers,系統範圍 /etc/subversion/config 和 /etc/subversion/servers)
為了回應各種問題和要求,Subversion 開發人員已撰寫一個 Python 腳本,可將純文字密碼儲存至快取中。如果您了解安全性影響,已排除其他替代方案,而且仍然想要將密碼以純文字快取在磁碟上,您可以在我們主幹的 tools/client-side/ 目錄中找到腳本 (截至撰寫本文為止)。
有關密碼快取的更多資訊,請參閱 Subversion 書籍 的第 6 章,在 "Client Credentials Caching"。
APR 0.9 分支的早期版本(Apache 2.0.x 和 Subversion 1.x 使用)不支援複製大型檔案(2Gb 以上)。已套用修正程式來解決「svnadmin hotcopy」問題,並包含在 APR 0.9.5+ 和 Apache 2.0.50+ 中。此修正程式並非適用於所有平台,但適用於 Linux。
注意:這假設儲存庫是由 Apache 2.0.x 提供服務。
在 APR 0.9.6 中 有一個錯誤,當它執行於 Tiger 時會發生,而且當您嘗試簽出大於 64Kb 的檔案時會出現。產生的簽出會失敗,通常會顯示無法預測的錯誤訊息。以下是您在用戶端可能會看到的一些範例,您遇到的特定錯誤可能有所不同
svn: Invalid diff stream: [tgt] insn 1 starts beyond the target view position
svn: Unexpected end of svndiff input
svn: REPORT request failed on '/path/to/repository' svn: REPORT of '/path/to/repository/!svn/vcc/default': Chunk delimiter was invalid
Apache error_log 中也可能會有錯誤,例如
[error] Provider encountered an error while streaming a REPORT response. [500, #0] [error] A failure occurred while driving the update report editor [500, #190004]
要確認此錯誤的存在 — 假設您可以存取提供儲存庫服務的機器 — 請嘗試使用 file:// URL 進行簽出,這將直接存取檔案系統,而不是透過 Apache。如果產生的簽出順利完成,那麼幾乎可以確定這就是問題所在。
目前,最好的解決方案是升級到 APR 1.2.0+。
或者,您可以從各自的原始碼重新建置 Apache 和 Subversion,在為 Apache 執行 configure 之前設定下列環境變數
setenv ac_cv_func_poll no
或以 Bourne shell 語法,如下所示
ac_cv_func_poll=no; export ac_cv_func_poll
如果您是分別建置 APR/APRUTIL(亦即,您並未使用 Apache tarball 中附帶的 APR/APRUTIL),您必須在執行 APR 的 configure 之前設定該環境變數,因為問題就出在這裡。
如果您在 Subversion trunk 來源建置的最後連結階段看到類似這樣的錯誤
/usr/local/apache2/lib/libaprutil-0.so.0: undefined reference to `db_create' /usr/local/apache2/lib/libaprutil-0.so.0: undefined reference to `db_strerror'
這可能是因為您使用的是 Debian GNU/Linux 系統,且需要升級「libtool」。(我也聽說 Debian 套件管理員必須調整「libtool」,這可能會對 Subversion 建置造成一些問題。但那只是道聽塗說 — 在撰寫此常見問題解答條目之前,我沒有時間驗證細節。不過,請參閱 https://svn.haxx.se/dev/archive-2006-02/1214.shtml 和它引發的討論串,以取得詳細說明。)
無論如何,在 2005 年 11 月 15 日於執行新發行升級「測試」版的 Debian GNU/Linux 系統上遇到此問題後,解決方案是使用標準的「./configure && make && sudo make install」範例,從來源建置 libtool 1.5.20。之後,我在 Subversion 工作副本樹中執行「make clean」、「./autogen.sh」、「./configure」、「make」,一切運作正常。
請注意,在 https://svn.haxx.se/dev/archive-2003-01/1125.shtml 出現了另一份關於這些症狀的報告,不過該討論串中並未提及在此說明的解決方案。
使用 --listen-host=0.0.0.0 選項呼叫 svnserve。Svnserve 無法正確支援 IPv4/IPv6 雙堆疊操作。請參閱 問題 #2382。
您嘗試新增的目錄已包含 .svn 子目錄,它是工作副本,但它來自與您嘗試新增到的目錄不同的儲存庫位置。這可能是因為您使用作業系統的「複製」指令(而非 svn copy)來複製此工作副本中的子目錄,或將其他工作副本複製到此工作副本中。
快速且粗略的解決方案是刪除您嘗試新增的目錄中包含的所有 .svn 目錄;這將讓「新增」指令完成。如果您使用 Unix,此指令將刪除 dir 下的 .svn 目錄
find dir -type d -name .svn -exec rm -rf {} \;
不過,如果複製來自同一個儲存庫,您理想上應該刪除或移開複製,並使用 svn copy 進行正確的複製,這將知道其歷史記錄並在儲存庫中節省空間。
如果複製來自不同的儲存庫,您應該自問為何進行此複製;您應該確保透過新增此目錄,您不會在儲存庫中製作它的不需要的副本。
這通常發生於 APR 編譯為使用 /dev/random,而伺服器無法收集足夠的熵。如果 Subversion 是伺服器上唯一使用 APR 的應用程式,您可以安全地重新編譯 APR,並將 --with-devrandom=/dev/urandom 選項傳遞給 configure。不過,這不應在使用 APR 進行其他程序的系統上執行,因為這可能會使其他服務不安全。
這可能是因為 OpenSSL 0.9.8 有問題。已知降級到舊版本(或升級到新版本)可以解決此問題。
svn: This client is too old to work with working copy '/path/to/your/working/copy'; please get a newer Subversion client這是因為 Subversion 的工作副本格式發生不兼容的變更,新版本的 Subclipse 升級了您的工作副本,因此現在您舊版的命令列程式無法讀取它。(此問題不限於 Subclipse;如果您使用 1.4 或更新的命令列用戶端,以及舊版的命令列用戶端,也會發生此問題。)解決方法很簡單,只要將您的命令列用戶端升級到 1.4 或更新版本即可。從 Subversion 1.5 開始,提供了一個輔助指令碼,可將工作副本降級為與 Subversion 舊版本相容的格式;請參閱 此常見問題集。
在工作副本中存在未版本化(且可能被忽略)的項目時,svn switch 有時會產生錯誤。切換會停止,使工作副本處於半切換狀態。
不幸的是,如果您採取錯誤的修正措施,可能會導致工作副本無法使用。有時在這種情況下,使用者會被指示執行 svn cleanup。但 svn cleanup 也可能會遇到錯誤。請參閱 問題 #2505。
使用者可以手動移除導致問題的目錄或檔案,然後執行 svn cleanup,並繼續切換,以從此情況中復原。
請注意,從原始乾淨的檢出切換永遠不會產生錯誤。如果您在開發過程中使用 svn switch,則有以下三種工作方式
# Check and delete svn unversioned files: svn status --no-ignore | grep '^[I?]' | sed 's/^[I?]//' svn status --no-ignore | grep '^[I?]' | sed 's/^[I?]//' | xargs rm -rf
一些範例在 問題 2505 中詳細說明。問題在於 svn 客户端採取安全措施,不想要刪除任何未版本化的項目。
這裡詳細說明兩個具體範例來說明這類問題。還有其他這裡未涵蓋的 svn 切換錯誤,您可以透過僅從原始簽出進行切換來避免這些錯誤。
wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Won't delete locally modified directory '<dir>' svn: Left locally modified or unversioned files
移除所有未版本化的檔案,並繼續切換將從此復原。
wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Won't delete locally modified directory '<dir>' svn: Left locally modified or unversioned files
在這種情況下,僅移除未版本化的項目並無法復原。清理失敗,但「svn 切換」會指示您執行「svn 清理」。
wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Directory '<dir>/.svn' containing working copy admin area is missing wc/$ svn cleanup svn: '<dir>' is not a working copy directory wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Working copy '.' locked svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)
移除目錄(以及所有其他未版本化的檔案,以防止「切換」在類似的錯誤上重複中斷),並繼續切換將從此復原。
TortoiseSVN 清理錯誤有點不同。您可能會遇到此問題
Subversion reported an error while doing a cleanup! <dir>/<anotherdir> is not a working copy directory
在這裡的每種情況中,「svn 切換」都會中斷,讓您留下半切換的工作副本。「svn 狀態」會顯示已切換項目的項目 S(與頂層目錄不同)、有問題目錄的 !,以及問題檔案的 ~(可能還有鎖定的 L)。像這樣
wc/$ svn status ! . ! <dir> S <switched_things> ~ <dir>/<thing_that_is_now_unversioned>
仔細檢視有關 命名檔案 的 Windows API 文件,可以發現造成此問題的最常見原因。簡而言之,使用 Windows 路徑函式的 Unicode 版本,以及提供絕對路徑指定符而非相對路徑指定符,可以處理更長的檔案名稱。很幸運地,Subversion 使用的 Apache Portable Runtime (APR) 函式庫會透明地將絕對路徑(例如 C:\WorkingCopy\file.txt)轉換成 Windows API 所需的格式 (\\?\C:\WorkingCopy\file.txt),然後再轉換回來。很不幸地,只有在使用絕對路徑時,才能享有這些長路徑的優點。
若要查看路徑長度是否為您所見問題的原因,請嘗試提供絕對目標路徑給 Subversion 命令列用戶端,而非相對路徑(或完全不提供)。換句話說,請執行下列動作,而非執行
C:\> svn up WorkingCopy
或執行
C:\> cd C:\WorkingCopy C:\WorkingCopy> svn up
執行
C:\> svn update C:\WorkingCopy
如果問題消失了,恭喜您 — 您已觸及 Windows 路徑長度限制。現在您已知道解決方法。
為何這個問題不會影響 TortoiseSVN?因為 TortoiseSVN 始終提供絕對路徑給 Subversion API。
那麼,為何 Subversion 命令列用戶端不會始終將其輸入轉換成絕對路徑並使用這些路徑?在 Subversion 1.7 之後,它會執行此動作。
有時,工作副本的元資料格式會在次要版本之間發生不兼容的變更。例如,假設您有一個使用 Subversion 1.4.4 建立的工作副本,但某天您決定試用 Subversion 1.5.0。之後,您嘗試切換回 1.4.4,但它無法運作 — 它只會顯示上述錯誤。
這是因為 1.5.0 將您的工作副本格式升級為支援一些新功能(在本例中,變更清單、keep-local 旗標和變動深度目錄)。儘管 1.4.4 不知道這些新功能,但它至少可以辨識工作副本格式已升級為它無法處理的版本。
1.5.0 升級工作副本是有充分理由的:它知道 1.4.4 不知道這些新功能,而且如果 1.4.4 現在要干預工作副本的元資料,可能會遺失重要資訊,可能導致損毀(例如,請參閱 問題 #2961)。
Subversion 1.7.0 和更新版本不會升級工作副本,除非您明確要求它們這麼做。(不過,升級工作副本是必要的;Subversion 1.7.0 無法在較早的 Subversion 建立或使用的工作副本上執行。)
Subversion 1.6.x 和更早版本會在第一次接觸工作副本時自動升級工作副本。如果您只想試用 Subversion 的新版本,而不打算永久安裝它,這種行為可能會很煩人。因此,我們會散布一個腳本,可以在安全的情況下降級工作副本。
https://svn.apache.org/repos/asf/subversion/trunk/tools/client-side/change-svn-wc-format.py
使用「--help」選項執行該腳本,以了解如何使用它。(它可以將 1.6.x 工作副本降級為 Subversion 1.4.x 和 1.5.x 可用的格式,但無法降級 1.7.x 工作副本。)
隨著 Subversion 的未來版本發布,我們將盡量讓此常見問題解答條目保持最新,以提供潛在的降級情境及其影響。
Neon 函式庫用於透過 HTTP 在 Subversion 伺服器和用戶端之間進行通訊,通常會建置為靜態函式庫。但它會隨後連結到不同的共用函式庫。這會在 64 位元 AMD 系統上造成建置過程中的錯誤,類似於此
subversion-1.4.6/neon/src/.libs/libneon.a(ne_request.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC /home/jrandom/subversion/subversion-1.4.6/neon/src/.libs/libneon.a: could not read symbols: Bad value
開發人員清單上有一個關於此問題的討論串。
解決方案是將 "--enable-shared" 選項提供給 Subversion 的設定指令碼。
簡而言之,此錯誤代表一類問題,當 Apache 錯誤地認為您的 Subversion 用戶端不再關注它與 Apache 建立的網路連線時,可能會發生此類問題。在類似情況下,已報告其他錯誤訊息,具體取決於連線是否使用 SSL,或 Apache 確切決定終止連線的時間。
Subversion 用戶端會嘗試隨時讓工作副本保持正常狀態。在結帳期間,它執行此項操作的方法之一是將已結帳檔案的原始版本隱藏起來,直到已擷取給定目錄的所有檔案和子目錄。一旦目錄的所有資料都已下載,用戶端會「完成」該目錄,將檔案的原始版本複製到工作區,修改管理資料,等等。在進行此目錄完成時,用戶端會專注於該任務,不會關注結帳網路串流。有時,通常在版本化目錄包含異常大量的檔案或大量異常大型檔案的情況下,用戶端可能會花費大量時間完成目錄(並忽略網路串流),以至於 Apache 認為用戶端已永久離開,因此 Apache 會終止連線。當用戶端最終將注意力轉回網路串流時,它會發現伺服器已放棄連線,並將此報告為錯誤。
解決此情況的一種方法是增加 Apache 願意等待用戶端證明其仍在監聽網路串流的時間。您可以透過調整 Apache Timeout 設定值向上調整。不過,建議您評估您的資料集。如果單一目錄中有大量檔案會在簽出期間造成問題,則很可能會在其他地方造成其他問題。如果您能將檔案集合分割成幾個檔案數較少的子目錄,這可能會普遍有益。
當您提交時,只有實際上因為提交而變更的檔案/目錄會將其基本版本升級到工作副本中的 HEAD。其他檔案/目錄(可能包括您從中提交的目錄!)不會升級其基本版本,這表示 Subversion 仍將它們視為基於過時的版本。另請參閱 此問題 和 Subversion 書籍的此區段。
這可能會令人困惑,特別是因為您可能會對自己造成樹狀結構衝突。例如,如果您將檔案新增到目錄並提交,然後在本地將該目錄移到其他地方,然後嘗試提交,此第二次提交將因目錄本身仍基於過時版本而失敗,並出現過時錯誤。更新時,將標記樹狀結構衝突。
Subversion 目前無法得知您自己在第二次提交期間提交了導致目錄過時的變更。而且允許提交過時目錄可能會導致無法偵測到某些樹狀結構衝突,因此 Subversion 不允許您這麼做。
為避免此問題,請務必在進行刪除、新增或移動檔案或目錄等結構變更之前更新整個工作副本。
當伺服器報告的主機名稱與 SSL 憑證中提供的名稱不符時,可能會發生此情況。請確定伺服器設定檔對 ServerName 和 NameVirtualHost 使用正確的值。
客戶端方面的修正方法是將 OpenSSL 更新至 1.0.0d 版本。請參閱 這篇發佈至 Subversion 開發人員郵件清單的文章 以取得詳細資訊。
如果憑證發行者未被 SVN 客戶端認定為「受信任」,就會發生此錯誤。Subversion 會詢問您是否信任該憑證,以及是否要儲存此憑證。
$ svn info https://mysite.com/svn/repo
Error validating server certificate for 'https://mysite.com:443':
- The certificate is not issued by a trusted authority. Use the
fingerprint to validate the certificate manually!
Certificate information:
- Hostname: mysite.com
- Valid: from Wed, 18 Jan 2012 00:00:00 GMT until Fri, 18 Jan 2013
23:59:59 GMT
- Issuer: Google Inc, US
- Fingerprint:
34:4b:90:e7:e3:36:81:0d:53:1f:10:c0:4c:98:66:90:4a:9e:05:c9
(R)eject, accept (t)emporarily or accept (p)ermanently?
在某些情況下,即使您輸入「p」選項接受此憑證,下次存取 SVN 時,仍會再次出現相同的錯誤。原因可能有多種。問題可能是您的 ~/.subversion 目錄權限錯誤,因此每次您想要永久新增憑證時,svn 實際上無法執行此動作,也不會通知您無法執行此動作。
可以透過在
~/.subversion/auth/svn.ssl.server
目錄中使用 chmod 644 修復權限,或刪除目錄內容來解決此問題。如果刪除目錄內容,下次存取儲存庫時,目錄會自動填入內容。
檔案位於儲存庫中;您可以透過執行 svn ls -R 等指令,或嘗試從儲存庫簽出工作副本來驗證這一點。
$ pwd /var/srv/repositories/foo $ ls -1 conf db format hooks locks README.txt $ svnlook youngest /var/srv/repositories/foo 1 $ svn ls file:///var/srv/repositories/foo trunk/ tags/ branches/
版本控制的文件和目錄並非儲存在磁碟的樹狀結構中(例如 CVS 儲存庫),而是儲存在資料庫檔案中。BDB 後端使用 Berkeley DB 資料庫,而 FSFS 後端使用自訂檔案格式,未來可能會使用 SQLite 資料庫。
一般來說,為了避免某些類型的錯誤合併衝突,可以記住下列規則
在複製過程中,如果來源是 URL,而目標是 URL 或在工作副本中,則會在複製目標上建立明確的合併資訊。這樣做的目的是,當使用下列指令建立分支時
svn copy ^/trunk ^/branches/mybranch稍後再使用類似下列指令將祖先無關的子樹複製到分支中
svn copy ^/branches/another-branch/foo ^/branches/mybranch/bar目錄 /branches/mybranch/bar 不會從其父目錄 /branches/mybranch 繼承合併資訊。從父目錄繼承的合併資訊可能無法反映新子目錄實際正確的合併歷程。
在來源和目標都在工作副本中的拷貝期間,不會在拷貝目標上建立合併資訊(在 Subversion 1.5.5 中)。這假設在主幹(或分支)上新增一個新的子項,並且此新增項目已合併到另一個分支,而該分支會使用定期追趕合併來保持同步。在此情況下,分支的新子項的繼承合併資訊是正確的,而建立明確的合併資訊可能會導致虛假的合併衝突,這是因為子項和父項的合併歷程記錄有明顯但事實上不正確的差異。
如需有關此行為的更多詳細資料和討論,請參閱使用者郵件清單上的這篇文章。
包含非 ASCII 字元的密碼可能無法與 Subversion 支援的基本驗證機制可靠地運作。這是因為用戶端和伺服器系統之間潛在的字元編碼差異。請參閱這篇郵件清單文章以取得詳細資料。
作為解決方法,您可以將 Subversion 伺服器設定為使用單一登入機制,例如 Kerberos 或 SSPI。請參閱Apache HTTPD 伺服器文件以取得詳細資料。如果您使用 svnserve,請參閱 Subversion 書籍中的「使用 svnserve 與 SASL」章節。
在使用 svnserve 與 SSH 驗證時,SSH 金鑰可用於解決密碼的此限制。
如果您看到透過 HTTP(S) 提供服務的 Subversion 儲存庫的伺服器端複製(又稱為分支或標記)速度很慢,您可能會遇到 問題 4531。此問題是由於伺服器上的 httpd 的 mod_dav 模組對「待複製樹狀結構」進行爬取所造成(讓複製的效能成本為 O(sizeof(tree)),而不是 Subversion 分支/標記通常的 O(1))。此行為出現在Apache httpd 版本 2.2.25(或更高版本)和2.4.6(或更高版本)中,較舊版本的 httpd 不受影響。因此,對大型樹狀結構進行分支/標記可能需要花費數分鐘。
此問題已在 Subversion 1.8.14 的 mod_dav_svn 中修復。您也可以使用下列解決方法讓 mod_dav 略過不必要的作業;將下列指令新增到伺服器上的 Apache 設定檔中,最好只新增到為 SVN 設定的 Location 區塊內
SetEnvIf Request_Method COPY method_is_copy RequestHeader set Depth 0 env=method_is_copy
這會在每個 COPY 要求中新增一個標頭「深度」,其值為 0。這會讓 mod_dav 避免爬取待複製的樹狀結構(但仍可讓 Subversion 執行正常的遞迴複製)。
請參閱 此郵件串以取得更多詳細資料。
SSL 通訊錯誤可能有多種原因。您可以使用 openssl 二進位檔來偵錯 ssl 連線。
openssl s_client -connect example.com:443 -servername example.com如果您使用用戶端憑證,則需要先將 Subversion 的用戶端憑證從 pkcs12 轉換為 pem
openssl pkcs12 -in path/to/svn/cert.p12 -out cert.pem然後您可以使用
openssl s_client -connect example.com:443 -servername example.com -cert cert.pem如果您在 .subversion/servers 中使用 ssl-authority-files 來驗證伺服器憑證,您可以讓 s_client 使用額外參數執行相同的動作
openssl s_client ... -CAfile path/to/authority.pems_client 輸出可能會指出發生什麼問題。
例如,如果 s_client 回報
error setting certificate 140258270184704:error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak:../ssl/ssl_rsa.c:303:則建立新的 CA 金鑰(使用 sha256 而非 md5)應可解決此問題。
在 unix 系統上執行 make install
步驟之前,Subversion 原始程式碼樹中的動態建置「可執行檔」實際上是 libtool 所產生的 shell 腳本,會重新連結並執行真正的二進位檔。如下所示,這會讓偵錯變得複雜
subversion$ gdb subversion/svn/svn
... "/path/to/subversion/subversion/svn/svn": 非可執行格式:無法辨識檔案格式
您可以透過 libtool 指令執行 gdb 來解決此問題。執行模式中的 libtool 指令會偵測 svn 指令是 libtool 包裝器腳本,並處理設定適當的環境變數,以及在執行 gdb 之前將腳本替換為真正的檔案路徑。
您的命令列會類似這樣
$ libtool execute gdb subversion/svn/svn
預設情況下,gcc 通常會最佳化私有變數和函式,內嵌相關操作。這會讓在偵錯程式中逐步執行程式碼變得複雜。
透過在 unix 系統上執行 make
步驟時關閉最佳化來解決此問題
subversion$ make EXTRA_CFLAGS=-O0
(這是「dash ohh zero」。)或者,您可以透過執行下列指令,讓此變更更為永久
subversion$ ./configure --enable-debug
對於生產安裝,請記得在從原始碼安裝 Subversion 之前,透過重新執行沒有額外標記的 make
或 configure
,來取消此操作。
Subversion 伺服器會對 mod_dav_svn 伺服器模組傳送 WebDAV/DeltaV 協定的子集。簡短的回答是
OPTIONS, PROPFIND, GET, REPORT, MKACTIVITY, PROPPATCH, PUT, CHECKOUT, MKCOL, MOVE, COPY, DELETE, LOCK, UNLOCK, MERGE
請注意,這個清單可能會隨著時間而增加:Subversion 1.7+ 開始在與 1.7+ 伺服器通訊時使用 POST 方法,而且 Subversion 1.9+ 可能會在與 1.9+ 伺服器通訊時開始使用另一種方法。
協定的詳細資訊記載於此處
https://svn.apache.org/repos/asf/subversion/trunk/notes/http-and-webdav/webdav-protocol請參閱 Poul-Henning Kamp 發表在 freebsd-hackers 的文章:https://docs.freebsd.org/en/books/faq/#bikeshed-painting。
Jim Blandy 既為 Subversion 命名,也設計了它的存放庫,他發音「Subversion」為 "Subversion"。
在 Subversion 的原始碼中,有許多地方提到「baton」物件。這些只是 void * 資料結構,它們為函式提供背景。在其他 API 中,它們通常稱為 void *ctx 或 void *userdata,Subversion 開發人員稱這些結構為「baton」,因為它們會被傳遞很多次。
楔入的儲存庫
Subversion 儲存庫包含兩個不同的內部部分,一個工作隔間和一個儲存隔間。楔入的儲存庫是一個工作隔間因某些原因無法存取,但儲存隔間完好的儲存庫。因此,楔入的儲存庫並未遺失任何資料,但必須修正工作隔間,才能存取儲存庫。有關如何執行的詳細資訊,請參閱此條目。
損毀的儲存庫
損毀的 Subversion 儲存庫是指儲存隔間已損毀的儲存庫,因此儲存庫中確實遺失了部分資料。
您可能也想要查看 The Jargon File 中「楔入」的定義。
Subversion 在我們的安全公告中使用 CVSSv3,因此您會在公告的嚴重性區段中看到 CVSSv3 基本分數和向量。CVSSv3 是常見漏洞評分系統的最新版本,這是一個用於評估電腦系統安全漏洞嚴重性的開放式產業標準。FIRST 維護此標準的文件。
分數為 0 到 10 之間的數字,風險較低的漏洞分數較低,風險較高的漏洞分數較高。分數是透過確定漏洞的指標,然後根據這些指標計算分數來計算的。如果您想要了解分數如何確定,您需要向量和對標準中所指定的公式的了解。
向量是適用於漏洞的指標的簡要說明。
CVSSv3 提供 3 種類型的指標和分數;基本、暫時和環境。Subversion 專案只會提供基本分數和指標。作為一個專案,我們無法確定各種安裝的環境風險,因此我們無法計算環境指標。暫時指標是針對可能隨時間改變的因素。我們不會在公告發布後更新公告,因此我們無法追蹤這些變動的值。
某些漏洞需要特定的組態或環境因素才能被利用。CVSSv3 規定存取複雜度指標應考慮此類組態的普遍性。因此,需要異常組態的漏洞將會有較低的分數。這些分數可以幫助您優先處理您需要對公告做出反應的速度,但由於存取複雜度指標,您仍應考慮漏洞如何影響您的安裝。
在計算伺服器漏洞的可用性影響指標時,Subversion 專案將使用 Subversion 中的「完成」值,而不是主機系統。例如,在考慮拒絕服務攻擊時,如果漏洞允許攻擊者讓 Subversion 伺服器完全無法存取,則可用性影響指標將計算為「高」。另一方面,如果攻擊只讓 Subversion 伺服器變慢或限制成功連線的數量,則會評為「低」。
在計算伺服器漏洞的完整性影響指標時,當 Subversion 儲存庫的歷程可能被變更或當主機系統上任何檔案的修改能力發生時,Subversion 專案將使用高值。在違反任何驗證或授權需求的情況下,變更任何檔案(同時保留適當的歷程追蹤)的能力將被視為低。
在計算伺服器漏洞的機密性影響指標時,當儲存庫中的所有檔案都可以讀取,而不論任何驗證或授權需求時,Subversion 專案將使用高值。如果只有部分檔案可以讀取,則將被視為低。
由於我們計算這些影響指標的方式,您可能會在漏洞資料庫或廠商公告中看到具有不同評分的公告。例如,提供 Subversion 二進制套件的 Linux 發行版可能會將系統上所主機的 Subversion 儲存庫內容的完全公開評分為僅為低機密性影響,導致較低的評分。
這可能是 Apache HTTP Server(版本 2.0.48 及更早版本)中已知錯誤所致,已提供修補程式,請參閱 https://bz.apache.org/bugzilla/show_bug.cgi?id=25040。您可能也想閱讀 https://issues.apache.org/jira/browse/SVN-1608,看看說明是否符合您的症狀。
您需要安裝 Windows XP Service Pack 1。
如果是即時儲存庫,那麼簡單的答案就是「您已安裝的 Berkeley DB 版本」。然而,如果它是來自備份或未知來源的儲存庫,而且您不知道它是由哪個版本的 Berkeley DB 建立的,以下是找出方法
執行一些指令,以查看儲存庫中編號最高的 db/log.* 檔案中,偏移量 12 和 16(十進位)的兩個 4 位元組整數。以下是使用 GNU od 的範例:「od -j12 -N8 -tx4 log.<number>」。以下是使用 Mac OS X hexdump 的範例:「hexdump -s12 -n8 -x log.<number>」。第一個整數應該是魔術數字 0x00040988,它將檔案識別為 Berkeley DB 日誌檔。第二個數字是日誌格式版本 - 使用下表將它與 Berkeley DB 版本配對
日誌格式版本 | Berkeley DB 版本 |
---|---|
5 (0x00000005) | 4.0 |
7 (0x00000007) | 4.1 |
8 (0x00000008) | 4.2 |
10 (0x0000000a) | 4.3 |
11 (0x0000000b) | 4.4 |
12 (0x0000000c) | 4.5 |
13 (0x0000000d) | 4.6 |
儲存庫在 repos/db/ 子目錄中的 Berkeley DB「環境」中儲存所有資料。該環境包含一組表格和一堆記錄檔 (log.*)。Berkeley DB 會記錄對表格進行的所有變更,以便在中斷時可以將表格復原為一致的狀態 (更多資訊)。
記錄檔會無限增長,耗盡磁碟空間,除非您 (作為儲存庫管理員) 採取一些措施。在任何特定時刻,Berkeley DB 僅使用少數記錄檔 (請參閱 這篇文章 及其相關討論串);其餘的可以安全刪除。如果您永遠保留所有記錄檔,理論上 Berkeley DB 可以從儲存庫建立之日起重播對其進行的每項變更。但在實際上,如果您正在進行備份,那麼這可能不值得花費磁碟空間。
使用 svnadmin
來查看可以刪除哪些記錄檔。您可能需要建立一個 cron 工作來執行此操作。
$ svnadmin list-unused-dblogs /repos /repos/db/log.000003 /repos/db/log.000004 [...] $ svnadmin list-unused-dblogs /repos | xargs rm # disk space reclaimed!
您也可以使用 Berkeley DB 的 db_archive
指令
$ db_archive -a -h /repos/db | xargs rm # disk space reclaimed!
另請參閱 svnadmin hotcopy
或 hotbackup.py
。
注意:如果您使用 Berkeley DB 4.2,Subversion 會建立啟用自動記錄檔移除功能的新儲存庫。您可以透過傳遞 --bdb-log-keep
選項給 svnadmin create
來變更此設定。請參閱 Berkeley DB 4.2.x 下載套件 中 docs/api_c/env_set_flags.html#DB_LOG_AUTOREMOVE 下的 Berkeley DB 手冊中的 DB_LOG_AUTOREMOVE
旗標。
儲存庫中的 Berkeley DB 資料庫對中斷很敏感。如果存取資料庫的程序在沒有「乾淨」關閉環境的情況下結束,則資料庫會處於不一致的狀態。造成此問題的常見原因包括
對於大多數情況,您應該執行「svnadmin recover」,這會將儲存庫倒回至一致的狀態;請參閱此問題以取得詳細資料。請注意,磁碟空間不足,加上頻繁的簽出或更新,可能會導致儲存庫以無法復原的方式崩潰(因此請保持備份)。
分段錯誤、強制終止和磁碟空間不足相當罕見。權限問題更為常見:一個處理程序存取儲存庫並意外變更擁有權或權限,然後另一個處理程序嘗試存取並因權限而中斷。
預防此問題的最佳方式是正確設定您的儲存庫權限和擁有權。請參閱此處以取得我們的建議。
您的儲存庫並未損毀,您的資料也未遺失。如果您的程序直接存取儲存庫(mod_dav_svn、svnlook、svnadmin,或如果您存取 `file://' URL),則它使用 Berkeley DB 存取您的資料。Berkeley DB 是一個記錄系統,表示它會在執行任何動作前記錄所有動作。如果您的程序中斷(Control-C 或區段錯誤),將會留下一個鎖定檔,以及描述未完成工作的記錄檔。任何嘗試存取資料庫的其他程序都只會暫停,等待鎖定檔消失。若要喚醒您的儲存庫,您需要要求 Berkeley DB 完成工作,或將資料庫倒轉至已知的一致狀態。
警告:如果您執行復原而另一個程序存取儲存庫,您可能會嚴重損毀您的儲存庫。
在執行此動作前,請務必完全停用對儲存庫的所有存取(關閉 Apache,從「svn」移除可執行權限)。請務必以擁有並管理資料庫的使用者身分執行此命令,而非以 root 身分執行,否則它會在 db 目錄中留下 root 擁有的檔案,而管理資料庫的非 root 使用者(通常是您或您的 Apache 程序)無法開啟這些檔案。在執行復原時,也請務必設定正確的 umask,否則會鎖定允許存取儲存庫的群組中的使用者。
只要執行
svnadmin recover /path/to/repos
命令完成後,請檢查儲存庫的 db
目錄中的權限。
有時「svnadmin 復原」無法運作。您可能會看到它顯示類似下列的錯誤
Repository lock acquired. Please wait; recovering the repository may take some time... svnadmin: DB_RUNRECOVERY: Fatal error, run database recovery svnadmin: bdb: Recovery function for LSN 175 7066018 failed on backward pass svnadmin: bdb: PANIC: No such file or directory svnadmin: bdb: PANIC: fatal region error detected; run recovery
或類似下列的錯誤
Repository lock acquired. Please wait; recovering the repository may take some time... svn: DB_RUNRECOVERY: Fatal error, run database recovery svn: bdb: DB_ENV->log_flush: LSN of 115/802071 past current end-of-log of 115/731460 svn: bdb: Database environment corrupt; the wrong log files may have been removed or incompatible database files imported from another environment [...] svn: bdb: changes: unable to flush page: 0 svn: bdb: txn_checkpoint: failed to flush the buffer cache Invalid argument svn: bdb: PANIC: Invalid argument svn: bdb: PANIC: fatal region error detected; run recovery svn: bdb: PANIC: fatal region error detected; run recovery [...]
在這種情況下,請嘗試使用 Berkeley DB 原生的 db_recover 實用程式(請參閱位於 Berkeley DB 4.2.x 下載套件 的 docs/utility/db_recover.html 下的 Berkeley DB db_recover 文件)。它通常位於 Berkeley DB 安裝的「bin/」子目錄中,例如,如果您從來源安裝 Berkeley DB,它可能是 /usr/local/BerkeleyDB.4.2/bin/db_recover;或者在 Berkeley DB 預先封裝的系統上,它可能只是 /usr/bin/db_recover。如果您已安裝多個版本的 Berkeley DB,請確保您使用的 db_recover 版本與建立存放庫時所使用的 Berkeley DB 版本相符。
使用「-c」(「災難性復原」)旗標執行 db_recover。您也可以新增「-v」以增加詳細資料,以及「-h」加上一個引數,告訴它要復原哪個 db 環境(因此您不必 cd 進入該目錄)。因此
db_recover -c -v -h /path/to/repos/db
使用擁有存放庫的同一個使用者執行此指令,而且再次絕對確定在您執行此指令時,沒有其他程序正在存取存放庫(例如,關閉 svnserve 或 Apache)。
如果您使用 http:// 存取,則「無法配置記憶體」錯誤會顯示在 httpd 錯誤記錄中,而且看起來像這樣
[Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (20014) Error string not specified yet: Berkeley DB error while opening 'strings' table for filesystem /usr/local/svn/repositories/svn/db: Cannot allocate memory [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] Could not fetch resource information. [500, #0] [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] Could not open the requested SVN filesystem [500, #160029] [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (17) File exists: Could not open the requested SVN filesystem [500, #160029]
這通常表示 Berkeley DB 存放庫已用盡資料庫鎖定(這不會發生在 FSFS 存放庫中)。這不應該在正常操作過程中發生,但如果發生,解決方案是執行資料庫復原,如 此處 所述。如果它經常發生,您可能需要提高 db/DB_CONFIG 檔案中的預設鎖定參數(set_lk_max_locks、set_lk_max_lockers 和 set_lk_max_objects)。在現有存放庫中變更 DB_CONFIG 時,請記得在之後執行復原。
您的 apr-util 連結到 DB-3,而 svn 連結到 DB-4。很不幸的是,DB 符號並不相同。當 mod_dav_svn 載入到 Apache 的處理程序空間時,它最後會針對 apr-util 的 DB-3 函式庫解析符號名稱。
解決方案是確定 apr-util 編譯時連結到 DB-4。您可以透過傳遞特定開關到 apr-util 或 apache 的 configure 來執行此動作:"--with-dbm=db4 --with-berkeley-db=/the/db/prefix"。
這並不是 Subversion 的問題,但它經常影響 Subversion 使用者。
Red Hat 9 和 Fedora 附帶的 Berkeley DB 函式庫仰賴核心支援 NPTL(原生 Posix 執行緒函式庫)。
Red Hat 提供的核心內建此支援,但如果您編譯自己的核心,則您可能沒有 NPTL 支援。如果是這種情況,您會看到類似這樣的錯誤
svn: Berkeley DB error svn: Berkeley DB error while creating environment for filesystem tester/db: Function not implemented
這可以用下列幾種方式之一來修正
LD_ASSUME_KERNEL
是否設定為 2.2.5
,如果是,請在啟動 Subversion (Apache) 之前取消設定。(您通常會設定此變數在 Red Hat 9 上執行 Wine 或 Winex)若要使用 Berkeley DB 的 NPTL 版本,您還需要使用具有 NPTL 支援的 glibc 函式庫,這可能表示 i686 版本。請參閱 https://svn.haxx.se/users/archive-2004-03/0488.shtml 以取得詳細資料。
Berkeley DB 4.1 已顯示出相當不穩定,4.0 和 4.2 都較佳。此錯誤訊息是 4.1 有時會中斷的獨特方式的徵兆。
問題在於,使用 Berkeley DB 後端的 Subversion 儲存庫所組成的其中一個資料表的資料庫格式欄位已損毀。由於不明原因,這幾乎總是「copies」資料表,它從「btree」類型切換到「recno」類型。以下是簡單的復原程序,如果它們沒有成功,您應該聯絡 Subversion 使用者 郵件清單。
在 Berkeley DB 4.3 之前,svnadmin recover 可用於就地升級 Berkeley DB 儲存庫。但是,由於 Berkeley DB 在版本 4.3 中的行為改變,這現在會失敗。
使用此程序將您的儲存庫原地升級至 Berkeley DB 4.3 或更新版本
現在儲存庫可以使用 Berkeley DB 4.3。