本文無條理性,僅作自我參考。
花費了兩個半下午,走馬觀花的看了一下說明文檔,SVN設計的太復雜,對我這樣的,不在一個集體的的業余開發者,要理解起來真是太難了。。。。
分支
Make branches as often as you want.(這是SVN官方說明中的一句話)
There's nothing special about this working copy; it simply mirrors a different directory in the repository.
版本控制系統的一個特性是能夠把各種修改分離出來放在開發品的一個分割線上。這條線被稱為分支。分支經常被用來試驗新的特性,而不會對開發有編譯錯誤的干擾。當新的特性足夠穩定之后,開發品的分支就可以混合回主分支里(主干線).
假設已經建立分支,如果其他人的 working copy 在trunk上,當你提交分支的更改時,主干不會發生改變。
分支背后的關鍵概念:You should remember two important lessons.
First, Subversion has no internal concept of a branch—it knows only how to make copies.When you copy a directory, the resultant directory is only a “branch” because you attach that meaning to it. You may think of the directory differently,or treat it differently, but to Subversion it's just an ordinary directory that happens to carry some extra historical information.
在版本庫中的復制,都是“廉價復制”。
Second, because of this copy mechanism, Subversion's branches exist as normal filesystem directories in the repository. This is different from other version control systems, where branches are typically defined by adding extra-dimensional “labels” to collections of files. The location of your branch directory doesn't matter to Subversion. Most teams follow a convention of putting all branches into a /branches directory, but you're free to invent any policy you wish.
合並(保持分支同步)
------frequently keeping your branch in sync with the main development line helps prevent “surprise” conflicts when it comes time for you to fold your changes back into the trunk.
由於有眾多的人參與項目,大多數人擁有主干拷貝是很正常的,任何人如果進行一個長周期的修改會使得主干陷入混亂,所以通常的做法是建立一個私有分支,提交修改到自己的分支,直到這階段工作結束。所以,好消息就是你和Sally不會互相打擾,壞消息是有時候分離會太遠。
記住“閉門造車”策略的問題,當你完成你的分支后,可能因為太多沖突,已經無法輕易合並你的分支和主干的修改。
相反,在你工作的時候你和Sally仍然可以繼續分享修改,這依賴於你決定什么值得分享,Subversion給你在分支間選擇性“拷貝”修改的能力,當你完成了分支上的所有工作,所有的分支修改可以被拷貝回到主干。在Subversion術語里,這種從一個分支復制修改到另一個分支的活動稱為合並,它是使用svn merge命令執行。
svn merge另一個常用的做法
是取消已經做得提交,假設你愉快的在/calc/trunk工作,你發現303版本對integer.c的修改完全錯了,它不應該被提交,你可以使用svn merge來“取消”這個工作拷貝上所作的操作,然后提交本地修改到版本庫,你要做得只是指定一個相反的區別。(你可以通過指定--revision 303:302--change -303
svn merge與svn diff
......At this point, the wise thing to do is look at the changes carefully with svn diff, and then build and test your branch. Notice that the current working directory (“.”) has also been modified; the svn diff will show that its svn:mergeinfo property has been either created or modified. This is important mergerelated metadata(元數據) that you should not touch, since it will be needed by future svn merge commands.
但是svn merge沒有這樣的保證,會導致很多的混亂:用戶可以詢問服務器比較任何兩個樹,即使一個與工作拷貝毫不相關的!這意味着有潛在的人為錯誤,用戶有時候會比較兩個錯誤的樹,創建的增量數據不會干凈的應用,svn merge會盡力應用更多的增量數據,但是有一些部分也許會難以完成,就像Unix下patch命令有時候會報告“failed hunks”錯誤,svn merge會報告“skipped targets”:
指出svn diff和svn merge區別的重要性在於,前一個命令忽略祖先,如果你詢問svn diff來比較文件foo.c的版本99和102,你會看到行為基礎的區別,diff命令只是盲目的比較兩條路徑,但是如果你使用svn merge是比較同樣的兩個對象,它會注意到他們是不關聯的,而且首先嘗試刪除舊文件,然后添加新文件,輸出會是一個刪除緊接着一個增加。
如果你使用svn merge進行比較,你會看到第一個目錄樹被刪除,而第二個樹添加上!在這個情況下,你僅僅是希望svn merge以路徑為基礎比較兩棵樹,而忽略文件和目錄的不相關性,當為合並命令添加--ignoreancestry選項時,就會像svn diff一樣工作。
切換
“Switching” a working copy that has no local modifications to a different branch results in the working copy looking just as it would if you'd done a fresh checkout of the directory. It's usually more efficient to use this command, because often branches differ by only a small degree. The server sends only the minimal set of changes necessary to make your working copy reflect the branch directory.
svn switch命令改變存在的工作拷貝到另一個分支,然而這個命令在分支上工作時不是嚴格必要的,它只是提供了一個快捷方式。在前面的例子里,完成了私有分支的建立,你取出了新目錄的工作拷貝,相反,你也可以簡單的告訴Subversion改變你的/calc/trunk的工作拷貝到分支的路徑。
svn switch命令也可以帶--revision(-r)參數,所以你不需要一直移動你的工作拷貝到分支的HEAD。
當然,許多項目比我們的calc要復雜的多,有更多的子目錄,Subversion用戶通常用如下的法則使用分支:
1. 拷貝整個項目的“trunk”目錄到一個新的分支目錄。
2. 只是轉換工作拷貝的部分目錄到分支。
切換和更新
Have you noticed that the output of svn switch and svn update looks the same? The switch command is actually a superset of the update command.
svn switch是svn update的一個變種,具有相同的行為,當新的數據到達時,任何工作拷貝的已經完成的本地修改會被保存。
當你運行svn update時,你會告訴版本庫比較兩個目錄樹,版本庫這樣做,並且返回給客戶區別的描述,svn switch和svn update兩個命令唯一區別就是update會一直比較同一路徑。That is, if your working copy is a mirror of /calc/trunk, svn update will automatically compare your working copy of /calc/trunk to /calc/trunk in the HEAD revision. If you're switching your working copy to a branch, svn switch will compare your working copy of /calc/trunk to some other branch directory in the HEAD revision.換句話說,一個更新通過時間移動你的工作拷貝,一個轉換通過時間和空間移動工作拷貝。
If the working copy needs to reflect(映射) a new directory within the repository, use just svns witch.If the working copy still reflects the same repository directory, but the location of the repository itself has changed, use svn switch with the --relocate option。
另一個Subversion模型的可愛特性是分支和標簽可以有有限的生命周期,就像其它的版本化的項目,舉個例子,假定你最終完成了calc項目你的個人分支上的所有工作,在合並了你的所有修改到/calc/trunk后,沒有必要繼續保留你的私有分支目錄。
在我們的例子里,你的個人分支只有一個相對短的生命周期:你會為修復一個Bug或實現一個小的特性來創建它,當任務完成,分支也該結束了。在軟件開發過程中,有兩個“主要的”分支一直存在很長的時間也是很常見的情況,舉個例子,假定我們是發布一個穩定
的calc項目的時候了,但我們仍會需要幾個月的時間來修復Bug,你不希望添加新的特性,但你不希望告訴開發者停止開發,所以作為替代,你為軟件創建了一個“穩定”分支...。
SVN可以為一個版本庫中的內容(主干)建立一個分支.分支和主干完全獨立,就相當於把代碼再復制(便宜復制)一份,重新添加到版本庫中。但SVN提供另一個功能,就是把主干做出的修改合並到分支中,以及把分支修改的內容合並到主干中。當然,我們也可以把主干的版本庫的路徑切換到分支上,然后更新,來實現把分支的修改更新到主干;以及修改分支路徑來同步主干的修改。但過程復雜,還容易出錯。
1.將一個整項目建一個分支.
選擇要復制的源位置有三個選項:
版本庫中的最新版本
新分支直接從倉庫中的最新版本里復制出來。不需要從你的工作副本中傳輸任何數據,這個分支的建立是非常快的。
在版本庫中指定具體的版本
在倉庫中直接復制建立一個新分支同時你也可以選擇一個舊版本。假如在你上周發布了項目時忘記了做標記,這將非常有用。如果你記不起來版本號,通過點擊鼠標右鍵來顯示版本日志,同時從這里選取版本號。和上次一樣不需要從你的工作副本中傳輸任何數據,這個分支建立起來是非常快的。
工作副本
新的分支是一個完全等同於你的本地工作副本的一個副本。如果你更新了一些文件到你的工作副本的某個舊版本里,或者你在本地做出了修改,這些改變將准確無誤的進入副本中。自然而然地這種綜合的標記會包含正在從工作副本傳輸到版本庫的數據,如果這些數據還不存在的話。
注意:是否把主干的路徑切換到新分支(把的工作副本自動切換到最新創建的分支)
如果勾選了,建立分支后,在主干里做出的修改並提交后,更新會提交到分支上。主干的版本源內容不會變.
但是如果你打算這么做,首先要確認你的工作副本沒有被修改。如果有修改的話,當你轉換后這些修改將會混合進你的工作副本分支里。按下確認提交新副本到版本庫中。別忘了提供一條日志信息。需要注意的是這個副本是在版本庫內部創建的。
為了避免產生困惑。以及失誤。建議在建立的時候不要勾上 "切換到分支" 的選項。如果勾上了,我們還是切換回去:
這時你便可以在 /calc/branches/my-calc-branch 分支上開發新的功能,且不會影響到其他成員開發或維護主干的內容。
切換操作起來就象更新,因為它沒有丟棄你在本地做的修改。在工作副本里當你進行切換的時候任何沒有提交過的修改都會被混合。如果你不想看到這樣的結果,那么你可以有兩種選擇,要么在切換前提交修改,要么把工作副本恢復到一個已經提交過的版本(比如最新版本)。
2.合並主干的變更到分支上
經常將 開發主干 ( /calc/trunk ) 的變更透過 svn merge 合並至 分支 ( /calc/branches/my-calc-branch )是一個非常好的習慣,這樣才不會讓你脫離主干(trunk) 過久而導致將分支 ( /calc/branches/my-calc-branch) 合並回 主干 ( /calc/trunk ) 時發生許多沖突。
從主干 ( /calc/trunk ) 合並至分支 ( /calc/branches/my-calc-branch ) 通常選第 1 個,也就是 [Merge a range of revisions]
注意.我們是在分支上使用的 Merge 功能.因為是要在分支上應用主干的更新.
在 Merge 的窗口有以下注意事項:
1.合並的來源,由於我們打算從主干 ( /calc/trunk ) 合並至分支 ( /calc/branches/my-calc-branch ),所以合並的來源要選 /calc/trunk 才對!
2.合並的結果會直接與目前「工作目錄」(Working Copy) 做比對,並修改目前工作目錄中的所有文件。因此建議在做合並之前可以將所有尚未 commit 的檔案先 commit 到版本庫,避免不必要的沖突事件發生。
在正式進行合並(Merge)之前,建議先執行 Test merge 看看是否會發生什么事!
若無異狀則可直接按下 [Merge] 按鈕進行合並動作,這時從 主干 ( /calc/trunk ) 分支出來的到目前工作目錄的版本就會做個比較,然后直接套用變更到你現有的文件、目錄或屬性里。
在合並之后如果沒有發生沖突,不代表真的沒沖突,所以必須再次對原始碼做出驗證后才能 commit 進版本庫,
建議可參考以下流程:
1.將項目進行建置(Build)
2.如果沒問題再對項目進行單元測試(Unit Testing)或手動測試(Manual Testing)
3.如果都沒問題再 commit 目前合並無誤的版本到版本庫!
If you encounter serious problems, you can always abort the local changes by running svn revert .
3.合並分支到主干
最后我們的 my-calc-branch 分支已經將新功能開發完成且測試無誤,所以要將 分支 ( calc/branches/mycalc-branch ) 的最終版本合並回 主干 ( /calc/trunk ),這時的手續如下:
從 分支 ( /calc/branches/my-calc-branch ) 合並回 主干 ( /calc/trunk ) 通常選第 2 個,而特別選擇[Reintegrate a branch] 這個選項是很重要的,因為這有以下好處:
1.讓 Subversion 能知道 主干 ( /calc/trunk ) 是從哪個分支、哪些版本合並進來的
2.有效節省 Subversion Repository (SVN儲存庫) 的空間,因為不用重復儲存分支的所有變更信息
3.可以產生 Revision graph 得知項目開發的分支狀況
一樣可以先 測試合並(Test merge) 再正式進行 合並(Merge)
4.合並完后再將變更 commit 到版本庫
4.刪除使用完畢的分支
當 分支 ( /calc/branches/my-calc-branch ) 合並回 主干 ( /calc/trunk ) 並 commit 了之后,該分支就沒
用了,該分支如果未來不再更新或繼續開發,Subversion 也不會繼續追蹤這個分支的變更 (因為之前已經
Reintegrate 過了),建議將該分支刪除。
沒有必要繼續保留你的私有分支目錄。刪除已經完成的分支避免其他人繼續使用該分支開發,減少版本庫的復雜程度。
另參考:http://www.cnblogs.com/dabaopku/archive/2011/05/21/2052820.html