Maven:版本管理 【SNAPSHOT】【Release】【maven-release-plugin】【nexus】

什麼是版本管理

首先,這裏說的版本管理(version management)不是指版本控制(version control),可是本文假設你擁有基本的版本控制的知識,瞭解subversion的基本用法。版本管理中說得版本是指構件(artifact)的版本,而非源碼的版本(如subversion中常見的rXXX,或者git中一次提交都有個sha1的commit號)。git

好比我有一個項目,其artifactId爲myapp,隨着項目的進展,咱們會生成這樣一些jar:myapp-1.0-SNAPSHOT.jar,myapp-1.0.jar,myapp-1.1-SNAPSHOT.jar,myapp-1.0.1.jar等等。你可能會說,這很簡單啊,我在POM中改個version,mvn clean install不就完了?但這只是表面,本文我將講述,snapshot和release版本的區別,如何自動化版本發佈(若是你的項目有幾十個module,你就會以爲手工改POM來升級版本是很痛苦的事情),結合自動化發佈的過程,這裏還會介紹maven-release-plugin。此外,一些scm概念也會被涉及到,好比tag和branch。程序員

 

前提:版本控制

無論怎樣,咱們都須要創建一個項目並提交到SCM中,這裏我以subversion爲例。你得有一個配置好的subversion repository,這裏我創建了一個空的svn倉庫,其地址爲:https://192.168.1.100:8443/svn/myapp/ 如今,該目錄下只有三個空的典型的子目錄:/trunk/, branches/, tags/。分別用來存放主幹,分支,以及標籤。apache

接着將項目導入到svn倉庫中,到項目根目錄,運行以下命令:windows

svn import -m 'project initialization' https://192.168.1.100:8443/svn/myapp/trunk 
(注意,這麼作你會將目錄下全部文件導入到svn庫中,可是這其中某些目錄和文件是不該該被導入的,如/target目錄,以及eclipse相關的項目文件)架構

目前,咱們將項目的版本設置爲1.0-SNAPSHOT。app

 

爲何用SNAPSHOT?

我先說說若是沒有SNAPSHOT會是什麼樣子。假設你的項目有2個模塊,A,B,其中A依賴B。這三個模塊分別由甲,乙兩個我的負責開發。在開發過程當中,由於A是依賴於B的,所以乙每次作一個改動都會影響到甲,因而,乙提交了一些更改後,須要讓甲看到。這個時候,怎麼作呢?乙對甲說,「你簽出個人代碼,build一下就OK了」,甲有點不情願,但仍是照作了,簽出代碼,svn clean install,而後,發現build出錯了,有個測試沒有pass。甲鬱悶了,對乙說,「你的代碼根本不能用,我不想build,你build好了給我」,乙看了看確實本身的代碼build不過,因而回去解決了,而後打了個jar包,扔給甲,甲對了對groupId,artifactId,放到了本身的.m2/repository/目錄下,OK,能用了。eclipse

因而乙每次更新都這樣作,打包,複製,而後甲粘貼,使用……漸漸的,你們發現這是個很笨的辦法,這是純手工勞動阿,程序員最BS的就是重複勞動。一天,甲對乙說,「你知道nexus麼?你把你的jar發佈到nexus上就能夠了,我要用就自動去下載,這多棒!」乙說「哦?有這好東西,我去看看」因而乙發現了nexus這塊新大陸,併成功的發佈了B到nexus上。(見,Nexus入門指南,(圖文) )。maven

可是,請注意,咱們這裏的一切都假設沒有SNAPSHOT,所以若是乙不更改版本,甲下載一次如B-1.0.jar以後,maven認爲它已經有了正確的B的版本,就不會再從新下載。甲發現了這個問題,對乙說「你的更新我看不到,你更新了麼?」乙說「不可能!我看看」,因而檢查一下甲下載的C-1.0.jar,發現那是幾天前的。乙一拍腦殼,說「這簡單,我更新一下個人版本就行了,我發佈個B-1.1.jar上去,你更新下依賴版本」,甲照作了,彷佛這麼作是可行的。svn

這裏有一個問題,一次提交就更新一個版本,這明顯不是正確的管理辦法,此外,乙得不停的通知甲更新對B的依賴版本,累不累阿?1.0,或者說1.1,2.0,都表明了穩定,這樣隨隨便便的改版本,能穩定麼?測試

因此Maven有SNAPSHOT版本的概念,它與release版本對應,後者是指1.0,1.1,2.0這樣穩定的發佈版本。

如今乙能夠將B的版本設置成1.0-SNAPSHOT,每次更改後,都mvn deploy到nexus中,每次deploy,maven都會將SNAPSHOT改爲一個當前時間的timestamp,好比B-1.0-SNAPSHOT.jar到nexus中後,會成爲這個樣子:B-1.0-20081017-020325-13.jar。Maven在處理A中對於B的SNAPSHOT依賴時,會根據這樣的timestamp下載最新的jar,默認Maven天天 更新一次,若是你想讓Maven強制更新,可使用-U參數,如:mvn clean install -U 。

如今事情簡化成了這個樣子:乙作更改,而後mvn deploy,甲用最簡單的maven命令就能獲得最新的B。

 

從1.0-SNAPSHOT到1.0到1.1-SNAPSHOT

SNAPSHOT是快照的意思,項目到一個階段後,就須要發佈一個正式的版本(release版本)。一次正式的發佈須要這樣一些工做:

  1. 在trunk中,更新pom版本從1.0-SNAPSHOT到1.0
  2. 對1.0打一個svn tag
  3. 針對tag進行mvn deploy,發佈正式版本
  4. 更新trunk從1.0到1.1-SNAPSHOT

你能夠手工一步步的作這些事情,無非就是一些svn操做,一些pom編輯,還有一些mvn操做。可是你應該明白,手工作這些事情,一來繁瑣,而來容易出錯。所以這裏我介紹使用maven插件來自動化這一系列動做。

SCM

首先咱們須要在POM中加入scm信息,這樣Maven纔可以替你完成svn操做,這裏個人配置以下:

Xml代碼   收藏代碼
  1. <scm>  
  2.   <connection>scm:svn:http://192.168.1.100:8443/svn/myapp/trunk/</connection>  
  3.   <developerConnection>scm:svn:https://192.168.1.100:8443/svn/myapp/trunk/</developerConnection>  
  4. </scm>  

須要注意的是,不少windows使用的tortoiseSVN客戶端,而沒有svn命令行客戶端,這會致使Maven全部svn相關的工做失敗,所以,你首先確保svn --version可以運行。

分發倉庫

想要讓Maven幫咱們自動發佈,首先咱們須要配置好分發倉庫。關於這一點,見Maven最佳實踐:Maven倉庫——分發構件至遠程倉庫。

maven-release-plugin

緊接着,咱們須要配置maven-release-plugin,這個插件會幫助咱們升級pom版本,提交,打tag,而後再升級版本,再提交,等等。基本配置以下:

Xml代碼   收藏代碼
  1. <plugin>  
  2.   <groupId>org.apache.maven.plugins</groupId>  
  3.   <artifactId>maven-release-plugin</artifactId>  
  4.   <version>2.0-beta-7</version>  
  5.   <configuration>  
  6.     <tagBase>https://192.168.1.100:8443/svn/myapp/tags/</tagBase>  
  7.   </configuration>  
  8. </plugin>  

GAV我就很少解釋了,這裏咱們須要注意的是configuration元素下的tagBase元素,它表明了咱們svn中的tag目錄,也就是說,maven-release-plugin幫咱們打tag的時候,其基礎目錄是什麼。這裏,我填寫了svn倉庫中的標準的tags目錄。

提交代碼

接着,確保你的全部代碼都提交了,若是你有未提交代碼,release插件會報錯,既然你要發佈版本了,就表示代碼是穩定的,因此要麼要麼把代碼提交了,要麼把本地的更改拋棄了。

開始工做

如今,屏住呼吸,執行:

mvn release:prepare

執行過程當中,你會遇到這樣的提示:

What is the release version for "Unnamed - org.myorg:myapp:jar:1.0-SNAPSHOT"? (org.myorg:myapp) 1.0: :

——「你想將1.0-SNAPSHOT發佈爲何版本?默認是1.0。」我要的就是1.0,直接回車。

What is SCM release tag or label for "Unnamed - org.myorg:myapp:jar:1.0-SNAPSHOT"? (org.myorg:myapp) myapp-1.0: :

——「發佈的tag標籤名稱是什麼?默認爲myapp-1.0。」我仍是要默認值,直接回車。

What is the new development version for "Unnamed - org.myorg:myapp:jar:1.0-SNAPSHOT"? (org.myorg:myapp) 1.1-SNAPSHOT: :

——「主幹上新的版本是什麼?默認爲1.1-SNAPSHOT。」哈,release插件會自動幫我更新版本到1.1-SNAPSHOT,很好,直接回車。

而後屏幕刷阿刷,maven在build咱們的項目,並進行了一些svn操做,你能夠仔細查看下日誌。

那麼結果是什麼呢?你能夠瀏覽下svn倉庫:

  • 咱們多了一個tag:https://192.168.1.100:8443/svn/myapp/tags/myapp-1.0/,這就是須要發佈的版本1.0。
  • 再看看trunk中的POM,其版本自動升級成了1.1-SNAPSHOT。

這不正是咱們想要的麼?等等,好像缺了點什麼,對了,1.0尚未發佈到倉庫中呢。

再一次屏住呼吸,執行:

mvn release:perform

maven-release-plugin會自動幫咱們簽出剛纔打的tag,而後打包,分發到遠程Maven倉庫中,至此,整個版本的升級,打標籤,發佈等工做所有完成。咱們能夠在遠程Maven倉庫中看到正式發佈的1.0版本。

這但是自動化的 ,正式的 版本發佈!

 

Maven的版本規則

前面咱們提到了SNAPSHOT和Release版本的區別,如今看一下,爲何要有1.0,1.1,1.1.1這樣的版本,這裏的規則是什麼。

Maven主要是這樣定義版本規則的:

<主版本>.<次版本>.<增量版本>

好比說1.2.3,主版本是1,次版本是2,增量版本是3。

主版本通常來講表明了項目的重大的架構變動,好比說Maven 1和Maven 2,在架構上已經兩樣了,未來的Maven 3和Maven 2也會有很大的變化。次版本通常表明了一些功能的增長或變化,但沒有架構的變化,好比說Nexus 1.3較之於Nexus 1.2來講,增長了一系列新的或者改進的功能(倉庫鏡像支持,改進的倉庫管理界面等等),但從大的架構上來講,1.3和1.2沒什麼區別。至於增量版本,通常是一些小的bug fix,不會有重大的功能變化。

通常來講,在咱們發佈一次重要的版本以後,隨之會開發新的版本,好比說,myapp-1.1發佈以後,就着手開發myapp-1.2了。因爲myapp-1.2有新的主要功能的添加和變化,在發佈測試前,它會變得不穩定,而myapp-1.1是一個比較穩定的版本,如今的問題是,咱們在myapp-1.1中發現了一些bug(固然在1.2中也存在),爲了可以在段時間內修復bug並仍然發佈穩定的版本,咱們就會用到分支(branch),咱們基於1.1開啓一個分支1.1.1,在這個分支中修復bug,並快速發佈。這既保證了版本的穩定,也可以使bug獲得快速修復,也不一樣中止1.2的開發。只是,每次修復分支1.1.1中的bug後,須要merge代碼到1.2(主幹)中。

上面講的就是咱們爲何要用增量版本。

 

實戰分支

目前咱們trunk的版本是1.1-SNAPSHOT,其實按照前面解釋的版本規則,應該是1.1.0-SNAPSHOT。

如今咱們想要發佈1.1.0,而後將主幹升級爲1.2.0-SNAPSHOT,同時開啓一個1.1.x的分支,用來修復1.1.0中的bug。

首先,在發佈1.1.0以前,咱們建立1.1.x分支,運行以下命令:

mvn release:branch -DbranchName=1.1.x -DupdateBranchVersions=true -DupdateWorkingCopyVersions=false

這是maven-release-plugin的branch目標,咱們指定branch的名稱爲1.1.x,表示這裏會有版本1.1.1, 1.1.2等等。updateBranchVersions=true的意思是在分支中更新版本,而updateWorkingCopyVersions=false是指不更改當前工做目錄(這裏是trunk)的版本。

在運行該命令後,咱們會遇到這樣的提示:

What is the branch version for "Unnamed - org.myorg:myapp:jar:1.1-SNAPSHOT"? (org.myorg:myapp) 1.1-SNAPSHOT: :

——"分支中的版本號是多少?默認爲1.1-SNAPSHOT" 這時咱們想要的版本是1.1.1-SNAPSHOT,所以輸入1.1.1-SNAPSHOT,回車,maven繼續執行直至結束。

接着,咱們瀏覽svn倉庫,會看到這樣的目錄:https://192.168.1.100:8443/svn/myapp/branches/1.1.x/,打開其中的POM文件,其版本已是1.1.1-SNAPSHOT。

分支建立好了,就可使用release:prepare和release:perform爲1.1.0打標籤,升級trunk至1.2.0-SNAPSHOT,而後分發1.1.0。

至此,一切OK。

 

小結

本文講述瞭如何使用Maven結合svn進行版本管理。解釋了Maven中SNAPSHOT版本的來由,以及Maven管理版本的規則。並結合SCM的tag和branch概念展現瞭如何使用maven-release-plugin發佈版本,以及建立分支。本文涉及的內容比較多,且略顯複雜,不過掌握版本管理的技巧對於項目的正規化管理來講十分重要。Maven爲咱們提供了一些一套比較成熟的機制,值得掌握。

 

注:本文轉自 http://juvenshun.iteye.com/blog/376422

相關文章
相關標籤/搜索