<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### 常見用例 分支和**svn merge**有很多不同的用法,這個小節描述了最常見的用法。 ### 合并一條分支到另一支 為了完成這個例子,我們將時間往前推進,假定已經過了幾天,在主干和你的分支上都有許多更改,假定你完成了分支上的工作,已經完成了特性或bug修正,你想合并所有分支的修改到主干上,讓別人也可以使用。 這種情況下如何使用**svn merge**?記住這個命令比較兩個目錄樹,然后應用比較結果到工作拷貝,所以要接受這種變化,你需要主干的工作拷貝,我們假設你有一個最初的主干工作拷貝(完全更新),或者是你最近取出了`/calc/trunk`的一個干凈的工作拷貝。 但是要哪兩個樹進行比較呢?乍一看,回答很明確,只要比較最新的主干與分支。但是你要意識到―這個想法是*錯誤的*,傷害了許多新用戶!因為**svn merge**的操作很像**svn diff**,比較最新的主干和分支樹不僅僅會描述你在分支上所作的修改,這樣的比較會展示太多的不同,不僅包括分支上的增加,也包括了主干上的刪除操作,而這些刪除根本就沒有在分支上發生過。 為了表示你的分支上的修改,你只需要比較分支的初始狀態與最終狀態,在你的分支上使用**svn log**命令,你可以看到你的分支在341版本建立,你的分支最終的狀態用`HEAD`版本表示,這意味著你希望能夠比較版本341和`HEAD`的分支目錄,然后應用這些分支的修改到主干目錄的工作拷貝。 ### 提示 查找分支產生的版本(分支的“基準”)的最好方法是在**svn log**中使用`--stop-on-copy`選項,log子命令通常會顯示所有關于分支的變化,包括 創建分支的過程,就好像你在主干上一樣,`--stop-on-copy`會在**svn log**檢測到目標拷貝或者改名時中止日志輸出。 所以,在我們的例子里, ~~~ $ svn log --verbose --stop-on-copy \ http://svn.example.com/repos/calc/branches/my-calc-branch … ------------------------------------------------------------------------ r341 | user | 2002-11-03 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines Changed paths: A /calc/branches/my-calc-branch (from /calc/trunk:340) $ ~~~ 正如所料,最后的打印出的版本正是`my-calc-branch`生成的版本。 如下是最終的合并過程,然后: ~~~ $ cd calc/trunk $ svn update At revision 405. $ svn merge -r 341:405 http://svn.example.com/repos/calc/branches/my-calc-branch U integer.c U button.c U Makefile $ svn status M integer.c M button.c M Makefile # ...examine the diffs, compile, test, etc... $ svn commit -m "Merged my-calc-branch changes r341:405 into the trunk." Sending integer.c Sending button.c Sending Makefile Transmitting file data ... Committed revision 406. ~~~ 再次說明,日志信息中詳細描述了合并到主干的的修改范圍,記住一定要這么做,這是你以后需要的重要信息。 舉個例子,你希望在分支上繼續工作一周,來進一步加強你的修正,這時版本庫的`HEAD`版本是480,你準備好了另一次合并,但是我們在[“合并的最佳實踐”一節]( "合并的最佳實踐")提到過,你不想合并已經合并的內容,你只想合并新的東西,技巧就是指出什么是“新”的。 第一步是在主干上運行**svn log**察看最后一次與分支合并的日志信息: ~~~ $ cd calc/trunk $ svn log … ------------------------------------------------------------------------ r406 | user | 2004-02-08 11:17:26 -0600 (Sun, 08 Feb 2004) | 1 line Merged my-calc-branch changes r341:405 into the trunk. ------------------------------------------------------------------------ … ~~~ 阿哈!因為分支上341到405之間的所有修改已經在版本406合并了,現在你只需要合并分支在此之后的修改―通過比較406和`HEAD`。 ~~~ $ cd calc/trunk $ svn update At revision 480. # We notice that HEAD is currently 480, so we use it to do the merge: $ svn merge -r 406:480 http://svn.example.com/repos/calc/branches/my-calc-branch U integer.c U button.c U Makefile $ svn commit -m "Merged my-calc-branch changes r406:480 into the trunk." Sending integer.c Sending button.c Sending Makefile Transmitting file data ... Committed revision 481. ~~~ 現在主干有了分支上第二波修改的完全結果,此刻,你可以刪除你的分支(我們會在以后討論),或是繼續在你分支上工作,重復這個步驟。 ### 取消修改 **svn merge**另一個常用的做法是取消已經做得提交,假設你愉快的在`/calc/trunk`工作,你發現303版本對`integer.c`的修改完全錯了,它不應該被提交,你可以使用**svn merge**來“取消”這個工作拷貝上所作的操作,然后提交本地修改到版本庫,你要做得只是指定一個相反的區別: ~~~ $ svn merge -r 303:302 http://svn.example.com/repos/calc/trunk U integer.c $ svn status M integer.c $ svn diff … # verify that the change is removed … $ svn commit -m "Undoing change committed in r303." Sending integer.c Transmitting file data . Committed revision 350. ~~~ 我們可以把版本庫修訂版本想象成一組修改(一些版本控制系統叫做*修改集*),通過`-r`選項,你可以告訴**svn merge**來應用修改集或是一個修改集范圍到你的工作拷貝,在我們的情況例子里,我們使用**svn merge**合并修改集#303到工作拷貝。 記住回滾修改和任何一個**svn merge**命令都一樣,所以你應該使用**svn status**或是**svn diff**來確定你的工作處于期望的狀態中,然后使用**svn commit**來提交,提交之后,這個特定修改集不會反映到`HEAD`版本了。 繼續,你也許會想:好吧,這不是真的取消提交吧!是吧?版本303還依然存在著修改,如果任何人取出`calc`的303-349版本,他還會得到錯誤的修改,對吧? 是的,這是對的。當我們說“刪除”一個修改時,我們只是說從`HEAD`刪除,原始的修改還保存在版本庫歷史中,在多數情況下,這是足夠好的。大多數人只是對追蹤`HEAD`版本感興趣,在一些特定情況下,你也許希望毀掉所有提交的證據(或許某個人提交了一個秘密文件),這不是很容易的,因為Subversion設計用來不丟失任何信息,每個修訂版本都是不可變的目錄樹 ,從歷史刪除一個版本會導致多米諾效應,會在后面的版本導致混亂甚至會影響所有的工作拷貝。 ### 找回刪除的項目 版本控制系統非常重要的一個特性就是它的信息從不丟失,即使當你刪除了文件或目錄,它也許從HEAD版本消失了 ,但這個對象依然存在于歷史的早期版本 ,一個新手經常問到的問題是“怎樣找回我的文件和目錄?” 第一步首先要知道需要拯救的項目是**什么**,這里有個很有用的比喻:你可以認為任何存在于版本庫的對象生活在一個二維的坐標系統里,第一維是一個特定的版本樹,第二維是在樹中的路徑,所以你的文件或目錄的任何版本可以有這樣一對坐標定義。 Subversion沒有向CVS一樣的`古典`目錄, 所以你需要**svn log**來察看你需要找回的坐標對,一個好的策略是使用**svn log --verbose**來察看你刪除的項目,--verbose選項顯示所有改變的項目的每一個版本 ,你只需要找出你刪除文件或目錄的那一個版本。你可以通過目測找出這個版本,也可以使用另一種工具來檢查日志的輸出 (通過**grep**或是在編輯器里增量查找)。 ~~~ $ cd parent-dir $ svn log --verbose … ------------------------------------------------------------------------ r808 | joe | 2003-12-26 14:29:40 -0600 (Fri, 26 Dec 2003) | 3 lines Changed paths: D /calc/trunk/real.c M /calc/trunk/integer.c Added fast fourier transform functions to integer.c. Removed real.c because code now in double.c. … ~~~ 在這個例子里,你可以假定你正在找已經刪除了的文件`real.c`,通過查找父目錄的歷史 ,你知道這個文件在808版本被刪除,所以存在這個對象的版本在此之前 。結論:你想從版本807找回`/calc/trunk/real.c`。 以上是最重要的部分―重新找到你需要恢復的對象。現在你已經知道該恢復的文件,而你有兩種選擇。 一種是對版本反向使用**svn merge**到808(我們已經學會了如何取消修改,見[“取消修改”一節]( "取消修改")),這樣會重新添加`real.c`,這個文件會列入增加的計劃,經過一次提交,這個文件重新回到`HEAD`。 在這個例子里,這不是一個好的策略,這樣做不僅把`real.c`加入添加到計劃,也取消了對`integer.c`的修改,而這不是你期望的。確實,你可以恢復到版本808,然后對`integer.c`執行取消**svn revert**操作,但這樣的操作無法擴大使用,因為如果從版本808修改了90個文件怎么辦? 所以第二個方法不是使用**svn merge**,而是使用**svn copy**命令,精確的拷貝版本和路徑“坐標對”到你的工作拷貝: ~~~ $ svn copy --revision 807 \ http://svn.example.com/repos/calc/trunk/real.c ./real.c $ svn status A + real.c $ svn commit -m "Resurrected real.c from revision 807, /calc/trunk/real.c." Adding real.c Transmitting file data . Committed revision 1390. ~~~ 加號標志表明這個項目不僅僅是計劃增加中,而且還包含了歷史,Subversion記住了它是從哪個拷貝過來的。在將來,對這個文件運行**svn log**會看到這個文件在版本807之前的歷史,換句話說,`real.c`不是新的,而是原先刪除的那一個的后代。 盡管我們的例子告訴我們如何找回文件,對于恢復刪除的目錄也是一樣的。 ### 常用分支模式 版本控制在軟件開發中廣泛使用,這里是團隊里程序員最常用的兩種分支/合并模式的介紹,如果你不是使用Subversion軟件開發,可隨意跳過本小節,如果你是第一次使用版本控制的軟件開發者,請更加注意,以下模式被許多老兵當作最佳實踐,這個過程并不只是針對Subversion,在任何版本控制系統中都一樣,但是在這里使用Subversion術語會感覺更方便一點。 #### 發布分支 大多數軟件存在這樣一個生命周期:編碼、測試、發布,然后重復。這樣有兩個問題,第一,開發者需要在質量保證小組測試假定穩定版本時繼續開發新特性,新工作在軟件測試時不可以中斷,第二,小組必須一直支持老的發布版本和軟件;如果一個bug在最新的代碼中發現,它一定也存在已發布的版本中,客戶希望立刻得到錯誤修正而不必等到新版本發布。 這是版本控制可以做的幫助,典型的過程如下: - *開發者提交所有的新特性到主干。* 每日的修改提交到`/trunk`:新特性,bug修正和其他。 - *這個主干被拷貝到“發布”分支。* 當小組認為軟件已經做好發布的準備(如,版本1.0)然后`/trunk`會被拷貝到`/branches/1.0`。 - *項目組繼續并行工作,*一個小組開始對分支進行嚴酷的測試,同時另一個小組在`/trunk`繼續新的工作(如,準備2.0),如果一個bug在任何一個位置被發現,錯誤修正需要來回運送。然而這個過程有時候也會結束,例如分支已經為發布前的最終測試“停滯”了。 - *分支已經作了標簽并且發布,*當測試結束,`/branches/1.0`作為引用快照已經拷貝到`/tags/1.0.0`,這個標簽被打包發布給客戶。 - *分支多次維護。*當繼續在`/trunk`上為版本2.0工作,bug修正繼續從`/trunk`運送到`/branches/1.0`,如果積累了足夠的bug修正,管理部門決定發布1.0.1版本:拷貝`/branches/1.0`到`/tags/1.0.1`,標簽被打包發布。 整個過程隨著軟件的成熟不斷重復:當2.0完成,一個新的2.0分支被創建,測試、打標簽和最終發布,經過許多年,版本庫結束了許多版本發布,進入了“維護”模式,許多標簽代表了最終的發布版本。 #### 特性分支 一個*特性分支*是本章中那個重要例子中的分支,你正在那個分支上工作,而Sally還在`/trunk`繼續工作,這是一個臨時分支,用來作復雜的修改而不會干擾`/trunk`的穩定性,不象發布分支(也許要永遠支持),特性分支出生,使用了一段時間,合并到主干,然后最終被刪除掉,它們在有限的時間里有用。 還有,關于是否創建特性分支的項目政策也變化廣泛,一些項目永遠不使用特性分支:大家都可以提交到`/trunk`,好處是系統的簡單―沒有人需要知道分支和合并,壞處是主干會經常不穩定或者不可用,另外一些項目使用分支達到極限:沒有修改*曾經*直接提交到主干,即使最細小的修改都要創建短暫的分支,然后小心的審核合并到主干,然后刪除分支,這樣系統保持主干一直穩定和可用,但是造成了巨大的負擔。 許多項目采用折中的方式,堅持每次編譯`/trunk`并進行回歸測試,只有需要多次不穩定提交時才需要一個特性分支,這個規則可以用這樣一個問題檢驗:如果開發者在好幾天里獨立工作,一次提交大量修改(這樣`/trunk`就不會不穩定。),是否會有太多的修改要來回顧?如果答案是“是”,這些修改應該在特性分支上進行,因為開發者增量的提交修改,你可以容易的回頭檢查。 最終,有一個問題就是怎樣保持一個特性分支“同步”于工作中的主干,在前面提到過,在一個分支上工作數周或幾個月是很有風險的,主干的修改也許會持續涌入,因為這一點,兩條線的開發會區別巨大,合并分支回到主干會成為一個噩夢。 這種情況最好通過有規律的將主干合并到分支來避免,制定這樣一個政策:每周將上周的修改合并到分支,注意這樣做時需要小心,需要手工記錄合并的過程,以避免重復的合并(在[“手工追蹤合并”一節]( "手工追蹤合并")描述過),你需要小心的撰寫合并的日志信息,精確的描述合并包括的范圍(在[“合并一條分支到另一支”一節]( "合并一條分支到另一支")中描述過),這看起來像是脅迫,可是實際上是容易做到的。 在一些時候,你已經準備好了將“同步的”特性分支合并回到主干,為此,開始做一次將主干最新修改和分支的最終合并,這樣以后,除了你的分支修改的部分,最新的分支和主干將會絕對一致,所以在這個特別的例子里,你會通過直接比較分支和主干來進行合并: ~~~ $ cd trunk-working-copy $ svn update At revision 1910. $ svn merge http://svn.example.com/repos/calc/trunk@1910 \ http://svn.example.com/repos/calc/branches/mybranch@1910 U real.c U integer.c A newdirectory A newdirectory/newfile … ~~~ 通過比較`HEAD`修訂版本的主干和`HEAD`修訂版本的分支,你確定了只在分支上的增量信息,兩條開發線都有了分枝的修改。 可以用另一種考慮這種模式,你每周按時同步分支到主干,類似于在工作拷貝執行**svn update**的命令,最終的合并操作類似于在工作拷貝運行**svn commit**,畢竟,工作拷貝不就是一個非常淺的分支嗎?只是它一次只可以保存一個修改。 Subversion項目有計劃,不管用什么方式,總有一天要實現**svnadmin obliterate**命令來進行永久刪除操作,而此時可以看[“svndumpfilter”一節]( "svndumpfilter")。 因為CVS沒有版本樹,它會在每個版本庫目錄創建一個`古典`區域用來保存增量數據。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看