<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 讓開發自動化: 針對廣大開發人員的并行開發 _Subversion 中的分支、標記和合并_ 雖然很多開發團隊都使用版本控制系統管理代碼變更,但當多個開發人員并行地使用不同的代碼庫進行編碼時,還是會出現問題的。在本期的 [_讓開發自動化_](http://www.ibm.com/developerworks/cn/java/j-ap/) 中,自動化專家 Paul Duvall 展示了如何運用開源的、免費的 Subversion 版本控制系統來有效地進行標記、分支和合并。 說到源代碼分支,可以將大多數的軟件開發團隊大致劃分為兩大陣營:有些是根本不分支;或存在大量的分支(甚至儲存庫),以致開發人員不知道從哪里簽入變更 — 或者覺得合并變更很痛苦,于是就冒險將這項工作推遲到軟件快要發布時才做。 ## 術語 _主干(trunk)_(有時稱 _head_)用于干線開發(mainline development)。_分支(branch)_是指一個代碼支線副本,用于進行與干線開發不同的變更。_標記(tag)_(有時稱 _標簽_)是一個使用時間戳的代碼支線副本,用于標識代碼支線,以在開發周期中返回到標記的地方。 永遠只需要操作主干是最理想的情況。這使合并兩個或多個代碼支線間的變更沒有那么復雜。然而,在現實的軟件開發中,您正在開發的可能是未來版本,或者有時您可能需要為一個已經交付使用的版本準備一條后路。你需要有權限訪問已發布版本的源代碼副本 — 但又不能擾亂正在開發的新代碼。 但當開發團隊試圖使用分開的代碼支線時,問題就會出現了。有些時候,開發團隊可能會選擇不創建分支,免得會延誤發布或導致開發人員瓶頸。而有些時候,開發人員合并的頻率太低,結果導致了合并沖突、瓶頸以及發布延誤。而增加分支則會使導航項目儲存庫很困難,從而導致開發人員無意中更改了不應該更改的代碼。 團隊進行并行開發時,一定要以最高的頻率將代碼合并回干線(即主干)。如果無法經常將代碼合并到主干的話,可以運行測試,這樣就能夠確定是否會發生合并沖突,從而使_實施_ 合并沒有那么困難。要有效地進行并行開發,您可以使用 Subversion(SVN)中的標記和分支,Subversion 是一個開源的、免費的源代碼管理系統。通過標記,團隊可以安全地返回到源代碼的前一版本中。 我將通過介紹以下內容來示范如何在 SVN 中進行并行開發: * 如何從主干創建一個 SVN 版本標記 * 根據版本標記來創建一個 SVN 分支 * 將變更合并回干線(即主干)的技巧 * 如何在開發中的主干運行持續集成(Continuous Integration,CI),以定期測試分支與主干的合并 * 演示如何將源于分支的變更應用到主干 * 舉例說明如何標記分支的源代碼 ## 關于本系列 作為開發人員,我們致力于自動化用戶流程;但許多開發人員卻疏忽了自動化自己的開發流程。為此,我們編寫了 [_讓開發自動化_](http://www.ibm.com/developerworks/cn/java/j-ap/) 系列文章,專門探討軟件開發流程自動化的實際應用,為您介紹_何時_ 以及_如何_ 成功應用自動化。 圖 1 顯示了幾個并行代碼支線的基本流程: ##### 圖 1\. 并行開發 ![](https://box.kancloud.cn/2016-05-11_5733314c12606.gif) 在圖 1 中,有效的開發發生在 SVN 主干的版本 1.0.0 和版本 1.1.0 之間。可以是一組開發人員在版本 1.0.1 分支上進行開發,而其他人員在干線上開發。 如果想要多個開發人員負責不同的代碼支線的話,可以使用很多策略和技巧。在本文中,我將展示一個很常用的方法,我曾在使用 SVN 的項目上用過它。 ## 為并行開發配置 Subversion 安裝和配置 SVN 服務器并不在本文的討論范圍之內。如果您有權限訪問一個有效的 SVN 服務器,就可以執行以下的步驟了: 1. 將 SVN 客戶機軟件下載到您的工作站。 2. 在工作站中創建一個標準本地目錄。 3. 將目錄添加到 SVN 儲存庫。 4. 將目錄提交到 SVN 儲存庫。 從 Tigris.org Web 站點(參見 [參考資料](#resources))為您的操作系統下載 SVN 客戶機軟件,并將其安裝到您的工作站。確保 SVN 可執行文件在您的工作站的系統目錄中。用 `svn co _URL_` 執行儲存庫的 SVN 簽出。 接下來,創建三個本地目錄: * 分支:用于維護干線開發之外的軟件。 * 標記:在發布軟件時用于標識變更集,以備使用。 * 主干:用于干線開發。 清單 1 展示了在 Windows?、Macintosh 以及基于 *nix 的系統上如何從命令行創建這些目錄: ##### 清單 1\. 創建本地目錄,將其添加到 Subversion ``` $ mkdir branches $ mkdir tags $ mkdir trunk ``` 在操作系統中創建了目錄之后,您可以分別使用 SVN `add` 和 `commit` 命令將它們添加并提交到 SVN。在我創建清單 1 的目錄的目錄中,我輸入了如清單 2 所示的命令(在適當的時候替代用戶憑證): ##### 清單 2\. 將本地目錄添加并提交到遠程 SVN 儲存庫 ``` $ svn add *.* $ svn commit -m "Setting up standard SVN branches, tags and trunk directories" \ --username tjefferson --password Mont!cello ``` 執行了清單 1 和清單 2 中的操作之后,SVN 儲存庫應該類似于圖 2: ##### 圖 2\. 在儲存庫中創建的標準 SVN 目錄 ![](https://box.kancloud.cn/2016-05-11_5733314c25ec1.jpg) 基本的 SVN 儲存庫就緒以后,就可以創建版本標記了。 * * * ## 根據主干創建一個版本標記 標記的用途是在某個特定點及時標識代碼支線副本,以便以后返回到該版本。圖 3 展示了一個名為 `brewery-1.0.0` 的標記,它是針對 `1.0.0` 版本創建的。(標記能夠隨時在任何點創建,但通常都是在發布軟件時創建)。 ##### 圖 3\. 為 SVN 主干創建一個惟一的標記 ![](https://box.kancloud.cn/2016-05-11_5733314c3c9a0.gif) 假設主干包含已發布的軟件的源代碼的話,第一個任務就是要依據主干創建一個 SVN 標記。清單 3 就是一個關于如何創建這個標記的例子: ##### 清單 3\. 根據主干創建一個版本標記 ``` <path id="svn.classpath"> <fileset dir="${lib.dir}"> <include name="**/*.jar" /> </fileset> </path> <taskdef name="svn" classpathref="svn.classpath" classname="org.tigris.subversion.svnant.SvnTask"/> <target name="create-tag-from-trunk"> <svn username="jhancock" password="S!gnhere"> <copy srcUrl="https://brewery-ci.googlecode.com/svn/trunk" destUrl="https://brewery-ci.googlecode.com/svn/tags/brewery-1.0.0" message="Tag created by jhancock on ${TODAY}" /> </svn> </target> ``` ## 安全驗證失敗 第一次運行使用 Hypertext Transfer Protocol 而不是 Secure Socket Layer 的 SVN 服務器時,一定要接受安全認證。如果您是第一次這樣從 Ant 腳本連接到安全 SVN 服務器,連接會失敗,并且不提供診斷信息。因此,第一次時,必須從命令行運行 SVN 命令連接到服務器。以后,您就可以從您的工作站運行任何 SVN Ant 腳本,以連接到該服務器。 清單 3 使用了由 Subclipse 開源項目提供的 SVN Ant 任務(下載地址請參見 [參考資料](#resources))。運行該 Ant 腳本時,一定要將隨 SVN Ant 任務一起提供的 JARs —svnant.jar、svnClientAdapter.jar 和 svnjavahl.jar— 包含在您的類路徑中。清單 3 的前半部分定義了這個類路徑。中間部分使用 `taskdef` 定義了 SVN Ant 任務。最后,我向主干和標記目錄執行了 SVN `copy` 命令,從而為這個版本提供一個惟一的名稱:`brewery-1.0.0`. 運行清單 3 中的腳本并創建了一個新標記之后,您的 SVN 儲存庫應該如圖 4 所示。儲存庫的根級下面是標記目錄(在 [清單 2](#listing2) 中創建)。而標記目錄的下面是在清單 3 中創建的新標記(目錄):brewery-1.0.0。它含有主干的副本。 ##### 圖 4\. 根據主干創建標記 ![](https://box.kancloud.cn/2016-05-11_5733314c4d3d8.jpg) 雖然標記的內容在 Subversion 中是可以更改的,但_千萬_ 不要這樣做。 * * * ## 根據版本標記創建一個分支 在技術上,根據版本標記創建分支與根據主干創建標記是相似的。兩者都要使用到 SVN 的 `copy` 命令。通常都會依照標記而創建分支,因為標記的是已_發布_ 的代碼的代碼副本 — 而不是正在開發的代碼(可能已經更改)。圖 5 展示了如何根據 `1.0.0` 版本標記創建 `1.0.1` 分支: ## 版本命名 人們一直都想找到一個簡單的版本命名的模式。但是,只要一個版本和下一個版本或不同項目之間所使用的版本命名模式稍有不同的話,麻煩就大了。版本模式可能有很多種。一定要選擇一個既簡單又能夠靈活處理將來的版本的模式。我所使用的模式是 major-version.minor-version.patch,它很簡單。Version 1.1.2 就是以這個命名模式命名的。也有些團隊選擇向版本追加一個構建號。 ##### 圖 5\. 根據 1.0.0 版本標記創建分支 1.0.1 ![](https://box.kancloud.cn/2016-05-11_5733314c67378.gif) 清單 4 通過 SVN Ant 任務調用了 SVN `copy` 命令,以將 `brewery-1.0.0` 標記中的所有文件拷貝到分支位置: ##### 清單 4\. 從版本標記創建分支的 Ant 腳本 ``` <target name="create-branch-from-tag"> <svn username="sadams" password="b0stonM@ss"> <copy srcUrl="https://brewery-ci.googlecode.com/svn/tags/brewery-1.0.0" destUrl="https://brewery-ci.googlecode.com/svn/branches/brewery-1.0.1" message="Branch created by sadams on ${TODAY}" /> </svn> </target> ``` 運行清單 4 中的腳本之后,SVN 儲存庫應該如圖 6 所示: ##### 圖 6\. 從版本標記創建分支 ![](https://box.kancloud.cn/2016-05-11_5733314c79cb3.jpg) ## 記住主干 有些團隊處理分支開發時很極端,他們所有的開發工作都從分支開始。要記住,根據主干進行開發會更輕松、更易于管理。分支就是為了并行地進行分開的開發。盡量不要濫用分支,動不動就創建分支。 在創建分支和使用 SVN Ant 任務時,一定要記得使用標記,這樣您才能夠提供一個可重復的過程,該過程方便源代碼的維護,使您可以輕松返回到上一版本的源代碼。 ### 根據分支運行 CI 通常 CI 過程都是根據儲存庫的干線(即主干)而運行的。但如果想集成開發人員在分支上的變更并檢查支線與干線的合并,這個原理也適用于分支。 圖 7 展示了 SVN 的位置。在這個 Hudson 配置頁面上,您還能夠定義要調用的 Ant 目標。 ##### 圖 7\. Hudson CI 服務器根據主干構建分支并測試合并 ![](https://box.kancloud.cn/2016-05-11_5733314c902af.jpg) 運行 Hudson 等 CI 服務器來測試合并可以提供一個預警系統,警告可能會在開發周期中發生潛在的合并沖突。 * * * ## 將分支的變更合并到主干 創建分支的主要原因之一就是防止中斷干線開發。但是,一定要將分支上的更改合并到主干。圖 8 展示了將版本 1.0.1 合并到干線,這個干線是軟件正在開發的版本 1.1.0: ##### 圖 8\. SVN 時間線 ![](https://box.kancloud.cn/2016-05-11_5733314caa303.gif) 在清單 5 中,我使用了 Subversion 的 `merge` 命令。我先輸入 `svn merge`,接著是合并到的目標 URL,然后是合并源的 URL,最后是本地目錄位置: ##### 清單 5\. 使用 SVN 的 `merge` 命令將分支開發合并到主干 ``` $ svn merge https://brewery-ci.googlecode.com/svn/trunk \ https://brewery-ci.googlecode.com/svn/branches/brewery-1.0.1 \ /dev/brewery --username pduvall --password password! ``` SVN Ant 任務沒有提供合并命令,因此需要從命令行運行 `merge` 命令。或者使用 Ant 的 `exec` 任務來運行它。 運行清單 5 中的命令會得到類似于圖 9 的結果: ##### 圖 9\. 將分支合并到主干的結果 ![](https://box.kancloud.cn/2016-05-11_5733314cbfb47.jpg) 如果合并成功,則需要提交 Subversion 中的變更,如清單 6 所示。在命令行上輸入 `svn commit`,然后輸入消息描述和主干的 SVN URL : ##### 清單 6\. 將合并后的變更提交到主干 ``` <target name="commit-branch-to-trunk"> <svn username="gwbush" password="IL0veTHEG00g!e"> <commit dir="${basedir}" message="Committing changes from brewery-1.0.1"> </commit> </svn> </target> ``` 要經常將變更從分支合并到主干以避免合并沖突,從而使代碼支線始終保持一致。 * * * ## 根據分支創建標記 為了根據特定的分支準備一個版本,我創建了一個 SVN 標記。這里使用方法與前面一些清單提供的方法類似。圖 10 展示了根據 `brewery-1.0.1` 分支創建名為 `brewery-1.0.1` 的標記的方法: ##### 圖 10\. 根據分支創建標記 ![](https://box.kancloud.cn/2016-05-11_5733314cd59e0.gif) 在特定的分支上完成開發后,就需要在 Subversion 中標記它。清單 7 展示了一個根據分支創建標記的例子: ##### 清單 7\. 根據分支創建 SVN 標記 ``` <svn username="jbartlett" password="newHampsh!re"> <copy srcUrl="https://brewery-ci.googlecode.com/svn/branches/brewery-1.0.1" destUrl="https://brewery-ci.googlecode.com/svn/tags/brewery-1.0.1" message="Branch created by jbartlett on ${TODAY}" /> </svn> ``` 根據具體分支創建標記之后,您就可以在以后的開發周期中返回到該版本了。 * * * ## 結束語 并行開發并不是什么難事,但如果不按照項目需求進行規劃并不斷改進,它的管理將非常困難。如果必須記住一點的話,那就是一切最終都要回到主干。您可以將分支看作是一個容納可能中斷干線開發的源代碼的臨時居所。最后要考慮的是要盡早地、經常地測試合并。當然可能有比 Subversion 更好的支持并行開發的版本控制系統,但根據我的經驗,開發團隊在開發時堅持原則比使用工具解決問題重要得多。
                  <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>

                              哎呀哎呀视频在线观看