使用release分支发布版本

目录

什么是release分支?

release分支是从develop分支拉出、为版本发布做准备的临时分支.release分支主要用于做最后时刻的bug修复以及发布相关信息的修改(比如,版本号、构建日期等).在release分支做这些事情有助于develop分支更清晰的合入下一个发布的特性.

develop分支拉出release分支存在一个关键时刻.在那个时刻,develop分支已经(基本)具备新发布想要的模样,至少所有本次发布需要的特性都已合入了develop分支.所有未来发布的特性都不得合入develop分支,必须等到那个时刻之后,release分支拉出才能合入.

将要发布的版本号在release分支拉出时确定.在此之前,develop分支上的变更只是属于"下一个发布",但这个发布到底会是0.3还是1.0在release分支拉出时明确,并遵循项目的版本号规则.

使用release分支发布版本流程

(黄色为develop分支,绿色为release分支,蓝色为master分支)

创建release分支

release分支从develop分支创建而来.假设,当前已发布的版本是1.1.5,我们马上要做一个新的发布.develop分支已经具备发布条件,并且我们决定让这次发布的版本号是1.2(不是1.1.6也不是2.0).因此,我们拉出release分支,并用新版本号命名这个分支:

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"

$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.

$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

创建完并切换分支后,我们变更了版本号(这里bump-version.sh是修改版本号的脚本),然后提交.

这个新分支会存在一段时间,直到发布完成.在这段时间内,新发现的bug需要修复在这个分支上,而不是develop分支.新特性绝不允许再合入这个分支,而要合入develop分支,等待下一次发布.

结束release分支

release分支的状态逐步稳定可以真正发布后,开始执行后续操作.首先,release分支需要合入master分支.然后,在master分支上打tag,以便日后更容易指向这个历史版本.最后,在release分支上的变更需要合回develop分支,保证未来的发布也会包含这些bug修复.

前两个步骤(发布完成,打标签):

$ git checkout master
Switched to branch 'master'

$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

$ git tag -a 1.2

release分支的变更合入develop分支:

$ git checkout develop
Switched to branch 'develop'

$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

这一步可能会引入合并冲突,因为我们变更了版本号.如果冲突,修复提交.

现在我们不再需要release分支,需要删除:

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

为什么要用release分支

release分支做最后的bug修复以及发布相关信息的修改(比如,版本号、构建日期等)有利于develop分支更清晰的合入下一个发布的特性,版本收敛与下一个发布的特性开发互不影响.

使用Git Flow进行版本发布

下面以一个实例详细描述如何使用gitflow进行版本发布。

假设我们有一个git仓库(Hadoop),已经被gitflow初始化,develop-2.7.4develop分支,master-2.7.4master分支。此时,develop-2.7.4已经具备了发布条件,所有准备在下一个发布交付的特性都已完成并合入develop-2.7.4develop-2.7.4的版本号是8.1.1-SNAPSHOT,也是我们下一个发布的版本号(这与我们上一节描述的版本号确定时间点不太一样,稍有提前,因为我们项目的版本号规则比较明确,所以在开始准备下一个发布时就已明确为8.1.1,又因为是在开发中,所以有-SNAPSHOT).

第一部分,开始发布

创建release分支

开始发布的第一个步骤是创建release分支,因为发布版本号已确定为8.1.1,所以release分支以8.1.1命名:

$ git flow release start 8.1.1
Switched to a new branch 'release/8.1.1'

Summary of actions:
- A new branch 'release' was created, based on 'develop-2.7.4'
- You are now on branch 'release/8.1.1'

Follow-up actions:
- Bump the version number now!
- Start committing last-minute fixes in preparing your release
- When done, run:

     git flow release finish '8.1.1'

$ git branch
  develop-2.7.4
  master-2.7.4
* release/8.1.1

更新develop分支版本号

release/8.1.1分支拉出后,当前发布开始.develop-2.7.4可以开始合入下一个发布的特性,但是需要先将版本号改为下一个发布的版本号.按照项目版本号规则,下一个发布的版本号为8.2.1,同时需要加上-SNAPSHOT

$ git checkout develop-2.7.4 
Switched to branch 'develop-2.7.4'
Your branch is up-to-date with 'origin/develop-2.7.4'.

$ ./change-version.sh "2.7.4" "8.1.1" "-SNAPSHOT" "V20.18.40.R1.B1" "2.7.4" "8.2.1" "-SNAPSHOT" "V20.18.40.R2.B1"
  ...
    <version>8.2.1-SNAPSHOT</version>
  <version>2.7.4-zdh8.2.1-SNAPSHOT</version>
SUCCESS!!

$ git commit -am "Preparing for 8.2.1-SNAPSHOT development"
[develop-2.7.4 1655a61] Preparing for 8.2.1-SNAPSHOT development
 1 file changed, 2 insertions(+), 2 deletions(-)

change-version.sh是每个组件自己的版本号修改脚本,参数对应关系如下:

OPENSOURCE_RELEASE=$1  # 当前发布的开源组件版本号
ZDH_RELEASE=$2  # 当前发布的ZDH版本号
SNAPSHOT_TAG=$3  # 当前发布的SNAPSHOT标签
PRODUCT_RELEASE=$4  # 当前发布的产品完整版本号,可能会用于产品对外显示
OPENSOURCE_NEXT_RELEASE=$5  # 下一个发布的开源组件版本号
ZDH_NEXT_RELEASE=$6  # 下一个发布的ZDH版本号
NEXT_SNAPSHOT_TAG=$7  # 下一个发布的SNAPSHOT标签
PRODUCT_NEXT_RELEASE=$8  # 下一个发布的产品完整版本号,可能会用于产品对外显示

修改完之后,hadoop版本号变为2.7.4-zdh8.2.1-SNAPSHOT

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.zte.zdh</groupId>
    <artifactId>zdh-parent</artifactId>
    <version>8.2.1-SNAPSHOT</version>
  </parent>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-main</artifactId>
  <version>2.7.4-zdh8.2.1-SNAPSHOT</version>
  <description>Apache Hadoop Main</description>
  <name>Apache Hadoop Main</name>
  <packaging>pom</packaging>

推送所有本地变更到远端

develop-2.7.4的变更提交Gerrit评审:

$ git log HEAD --not origin/develop-2.7.4 # 确保本地develop-2.7.4上只有版本号的变更
commit b99e1ca4886fce9f2702b36f948c647e6b158d0e
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 13:45:53 2018 +0800

    Preparing for 8.2.1-SNAPSHOT development

    Change-Id: Idb3ed63c29a7c6caeb26d098ac887b03cf3de11d
$ git push origin HEAD:refs/for/develop-2.7.4
  ...

因为release/8.1.1会存在一段时间,用于bug修复,所以需要将release/8.1.1推送到远端供bug修复:

$ git flow release publish 8.1.1
Warning: Permanently added '[gerrit.zte.com.cn]:29418,[10.41.103.20]:29418' (RSA) to the list of known hosts.
Warning: Permanently added '[gerrit.zte.com.cn]:29418,[10.41.103.20]:29418' (RSA) to the list of known hosts.
Total 0 (delta 0), reused 0 (delta 0)
remote: Processing changes: refs: 1, done    
To ssh://[email protected]:29418/DAP/ZDH/Hadoop
 * [new branch]      release/8.1.1 -> release/8.1.1
Warning: Permanently added '[gerrit.zte.com.cn]:29418,[10.41.103.20]:29418' (RSA) to the list of known hosts.
Already on 'release/8.1.1'
Your branch is up-to-date with 'origin/release/8.1.1'.

Summary of actions:
- A new remote branch 'release/8.1.1' was created
- The local branch 'release/8.1.1' was configured to track the remote branch
- You are now on branch 'release/8.1.1'

第二部分,在release分支做bug修复

在release分支做bug修复

release/8.1.1拉出、develop-2.7.4修改完版本号之后,下个发布的新特性可以开始合入develop-2.7.4,而release/8.1.1只做bug修复,不合新特性.

bug修复示意过程如下:

$ git checkout release/8.1.1

$ git commit -m "bugfix 1" && git push origin HEAD:refs/for/release/8.1.1
[release/8.1.1 cc62e0d] bugfix 1
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bugfix.1
 ...

$ git commit -m "bugfix 2" && git push origin HEAD:refs/for/release/8.1.1
[release/8.1.1 53c844d] bugfix 2
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bugfix.2
 ...

$ git commit -m "bugfix 3" && git push origin HEAD:refs/for/release/8.1.1
[release/8.1.1 4d39417] bugfix 3
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bugfix.3
 ...

将release分支的bug修复合回develop分支

release/8.1.1的bug修复可以定期合回develop-2.7.4或者每次bug修复完成就合回,或者什么都不做,因为后续release/8.1.1结束,那些没有被合回的修复还会被合回.到底采用哪种策略可根据实际情况确定.

建议尽早将修复都合回develop-2.7.4,因为越早合回,冲突的概率越低.

合回使用如下操作(合回完成后需提交Gerrit评审):

$ git checkout develop-2.7.4 
Switched to branch 'develop-2.7.4'
Your branch is up-to-date with 'origin/develop-2.7.4'.

$ git merge release/8.1.1 -m "Merge branch release/8.1.1 into develop-2.7.4"
Merge made by the 'recursive' strategy.
 bugfix.1 | 0
 bugfix.2 | 0
 bugfix.3 | 0
 3 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bugfix.1
 create mode 100644 bugfix.2
 create mode 100644 bugfix.3
[develop-2.7.4 4ab5a6c] Merge branch release/8.1.1 into develop-2.7.4
 Date: Thu Jan 11 15:31:56 2018 +0800

$ git commit --amend -C HEAD # 由于merge会产生一个空提交对象,但不会自动生成Change-Id,所以merge后使用commit --amend重新提交来生成Change-Id

$ git log
commit 8975b03c572b16686cbe5c50ddfd6b7b5cbe9235
Merge: 680a66e 4d39417
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 15:05:40 2018 +0800

    Merge branch release/8.1.1 into develop-2.7.4

  Change-Id: If0a7e058f9c5dca928a67d3d98d4214b9121912a # Change-Id已经重新生成

commit 680a66e88e98a4ad4117ff94e1fa79d8dce884e5
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 14:25:35 2018 +0800

    bugfix 3

    Change-Id: I36391cbdf465ace0d095f90c6616240f04d2aee0 

$ git push origin HEAD:refs/for/develop-2.7.4 # 由于bug修复已经在release分支上评审过,此处不会再触发Gerrit评审,只有新生成的空提交需要评审,以便流水线验证整体合回是否影响到develop分支
Counting objects: 2, done.
Delta compression using up to 24 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 356 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1)
remote: Processing changes: new: 1, refs: 1, done    
remote: 
remote: New Changes:
remote:   http://gerrit.zte.com.cn/1347516 Merge branch release/8.1.1 into develop-2.7.4
remote: 
To ssh://[email protected]:29418/DAP/ZDH/Hadoop
 * [new branch]      HEAD -> refs/for/develop-2.7.4

如果出现冲突,需要手工解决.

使用merge命令而不推荐使用cherry-pick合回release/8.1.1的bug修复,主要是因为merge会复用release/8.1.1上的提交对象,而cherry-pick会另生成一个提交对象,但另生成的对象与原对象的提交内容实际是一样的,所以使用merge会让提交记录更整洁.

第二部分的过程会持续一段时间,直到release/8.1.1的bug修复完成,功能趋于稳定.这个bug修复、功能收敛的过程越短越好.因为每次修复的bug都要合入两个分支,并且进行代码走查、流水线保护,无形增加了很多合入成本.因此要求我们在develop分支上就要尽可能做好质量保障.

第三部分,结束发布

release分支合入master

release/8.1.1趋于稳定后,可以开始结束发布的过程.
首先,将release/8.1.1的全部变更合入master-2.7.4

$ git checkout master-2.7.4
Switched to branch 'master-2.7.4'
Your branch is up-to-date with 'origin/master-2.7.4'.

$ git merge --no-ff release/8.1.1
Auto-merging pom.xml
CONFLICT (content): Merge conflict in pom.xml
Automatic merge failed; fix conflicts and then commit the result.

这时会产生冲突,因为master-2.7.4release/8.1.1对版本号都产生了变更,但变更后的值不一样.master-2.7.4将版本号从7.8.1-SNAPSHOT改为7.8.1,而release/8.1.1继承自develop-2.7.4,将版本号从7.8.1-SNAPSHOT改为8.1.1-SNAPSHOT

$ git diff pom.xml
diff --cc pom.xml
index 7d79ba7,28acb7e..0000000
--- a/pom.xml
+++ b/pom.xml
@@@ -27,11 -27,11 +27,19 @@@ xsi:schemaLocation="http://maven.apache
    <parent>
      <groupId>com.zte.zdh</groupId>
      <artifactId>zdh-parent</artifactId>
++<<<<<<< HEAD
 +    <version>7.8.1</version>
 +  </parent>
 +  <groupId>org.apache.hadoop</groupId>
 +  <artifactId>hadoop-main</artifactId>
 +  <version>2.7.3-zdh7.8.1</version>
++=======
+     <version>8.1.1-SNAPSHOT</version>
+   </parent>
+   <groupId>org.apache.hadoop</groupId>
+   <artifactId>hadoop-main</artifactId>
+   <version>2.7.4-zdh8.1.1-SNAPSHOT</version>
++>>>>>>> release/8.1.1
    <description>Apache Hadoop Main</description>
    <name>Apache Hadoop Main</name>
    <packaging>pom</packaging>

这时只需要保留8.1.1-SNAPSHOT这个版本就可以了,命令如下:

$ git checkout --theirs . # 此命令将所有的文件换成release/8.1.1的版本,相当于对所有冲突部分只保留release/8.1.1版本.
                          # 使用前需谨慎确保所有git status的变更文件都只是版本号相关文件,比如pom.xml,并且所有的冲突都是版本号相关
$ git add . # 将所有冲突修复后的文件加入暂存区
$ git commit -m "Merge branch release/8.1.1 into master-2.7.4"

此时,release/8.1.1的全部变更就已合入master-2.7.4

$ git checkout master-2.7.4

$ git log
commit e180be234b00862cc49ede7af54892dba9ae5aa4
Merge: 4eabf5e 4d39417
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 14:39:17 2018 +0800

    Merge branch release/8.1.1 into master-2.7.4

    Change-Id: I21f54ba7be946677d8878bc20ece800dcb249c75

commit 4d39417bf8cbb11ede1c94b57a64a5c5185afd5f
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 14:25:35 2018 +0800

    bugfix 3

    Change-Id: I36391cbdf465ace0d095f90c6616240f04d2aee0

commit 53c844d458d3bb165d9d68e2205fc47f65dfded4
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 14:25:15 2018 +0800

    bugfix 2

    Change-Id: I9f4a4b32ec6091a9aebd3cd9fdac0ffe1f721a00

commit cc62e0d19d4ee6daf548d40ed7f2fbf0db26e3fb
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 14:25:05 2018 +0800

    bugfix 1

    Change-Id: Ia22e56fe92f42b3c7e719196920013a77ee5a831

commit 4eabf5e307d39ceaf65fe7f9eb878e28f2ed1959
Author: 何文鑫10087558 <[email protected]>
Date:   Wed Jan 10 16:19:41 2018 +0800

    Release for 7.8.1

    Change-Id: I6532a84fc231338393f3c6a487d9074c42922a47

修改master分支版本号

release/8.1.1的全部变更合入master-2.7.4后,准备在master-2.7.4做正式发布,但之前需要在master-2.7.4上将版本号去掉-SNAPSHOT改为8.1.1

$ git checkout master-2.7.4 
Switched to branch 'master-2.7.4'
Your branch is up-to-date with 'origin/master-2.7.4'.

$ ./change-version.sh "2.7.4" "8.1.1" "-SNAPSHOT" "V20.18.40.R1.B1" "2.7.4" "8.1.1" "" "V20.18.40.R2.B1"
  ... 
    <version>8.1.1</version>
  <version>2.7.4-zdh8.1.1</version>
SUCCESS!!

$ git commit -am "Release for 8.1.1"
[master-2.7.4 5f31d41] Release for 8.1.1
 1 file changed, 2 insertions(+), 2 deletions(-)

master分支打tag

master-2.7.4上完成所有变更后,master-2.7.4上需要打tag标记,tag会被用来在master-2.7.4上进行紧急bug修复.

tag操作:

$ git tag -a -m release-8.1.1 release-8.1.1 # 为了与分支release/8.1.1区分,tag命名为release-8.1.1
$ git show release-8.1.1 
tag release-8.1.1
Tagger: 何文鑫10087558 <[email protected]>
Date:   Wed Jan 10 14:02:25 2018 +0800

release-8.1.1

commit cbae556b0449ae1e0bd2eb079dbf1bc02c1818d8
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 14:42:36 2018 +0800

    Release for 8.1.1

    Change-Id: I238662157a197f7107411ee79b0461e19f3dbaed

diff --git a/pom.xml b/pom.xml
index 28acb7e..db519f5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,11 +27,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
   <parent>
     <groupId>com.zte.zdh</groupId>
     <artifactId>zdh-parent</artifactId>
-    <version>8.1.1-SNAPSHOT</version>
+    <version>8.1.1</version>
   </parent>
   <groupId>org.apache.hadoop</groupId>
   <artifactId>hadoop-main</artifactId>
-  <version>2.7.4-zdh8.1.1-SNAPSHOT</version>
+  <version>2.7.4-zdh8.1.1</version>
   <description>Apache Hadoop Main</description>
   <name>Apache Hadoop Main</name>
   <packaging>pom</packaging>

确保所有bug修复都已合回develop

之前已经介绍过,应尽早将release/8.1.1的bug修复合回develop-2.7.4
此时,我们仍需要再进行一次合回,确保所有的bug修复都已合回develop-2.7,4

操作过程同之前的合回过程,不再赘述.

删除release分支

上述操作完成后,可以删除release/8.1.1

$ git branch -d release/8.1.1
Deleted branch release/8.1.1 (was 39b1d0c).

推送所有变更到远端

确保develop-2.7.4合回的所有变更都已提交,只有最后一个merge对象在Gerrit评审中:

$ git log develop-2.7.4 --not origin/develop-2.7.4
commit 4ab5a6c0bb0fb4d024193dfc2958f52a236fefe0
Merge: b99e1ca 4d39417
Author: 何文鑫10087558 <[email protected]>
Date:   Thu Jan 11 15:31:56 2018 +0800

    Merge branch release/8.1.1 into develop-2.7.4

    Change-Id: Id4054075e9c4e7a8be19cc02a865a2c9878e98f4

master-2.7.4的变更提交到Gerrit评审:

$ git checkout master-2.7.4
Already on 'master-2.7.4'
Your branch is ahead of 'origin/master-2.7.4' by 6 commits.
  (use "git push" to publish your local commits)

$ git push origin HEAD:refs/for/master-2.7.4
Warning: Permanently added '[gerrit.zte.com.cn]:29418,[10.41.103.20]:29418' (RSA) to the list of known hosts.
Counting objects: 4, done.
Delta compression using up to 24 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 631 bytes | 0 bytes/s, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2)
remote: Processing changes: new: 2, refs: 2, done    
remote: 
remote: New Changes:
remote:   http://gerrit.zte.com.cn/1347860 Merge branch release/8.1.1 into master-2.7.4
remote:   http://gerrit.zte.com.cn/1347861 Release for 8.1.1
remote: 
To ssh://[email protected]:29418/DAP/ZDH/Hadoop
 * [new branch]      HEAD -> refs/for/master-2.7.4

删除远端release/8.1.1

$ git push origin --delete release/8.1.1 
Warning: Permanently added '[gerrit.zte.com.cn]:29418,[10.41.103.20]:29418' (RSA) to the list of known hosts.
remote: Processing changes: refs: 1, done    
To ssh://[email protected]:29418/DAP/ZDH/Hadoop
 - [deleted]         release/8.1.1

推送本地tag到远端保存:

$ git push origin release-8.1.1
Counting objects: 11, done.                                                                                                       
Delta compression using up to 24 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1.49 KiB | 0 bytes/s, done.
Total 11 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5)
remote: Processing changes: refs: 1, done    
To ssh://[email protected]:29418/DAP/ZDH/Hadoop
 ! [remote rejected] release-8.1.1 -> release-8.1.1 (prohibited by Gerrit)
error: failed to push some refs to 'ssh://[email protected]:29418/DAP/ZDH/Hadoop'

结束发布过程完成.

最终,完整的各分支提交记录如下:

*   abc15c7 (HEAD -> develop-2.7.4, origin/develop-2.7.4) Merge branch release/8.1.1 into develop-2.7.4
|\  
* | b99e1ca Preparing for 8.2.1-SNAPSHOT development
| | * cbae556 (tag: release-8.1.1, origin/master-2.7.4, master-2.7.4) Release for 8.1.1
| | *   e180be2 Merge branch release/8.1.1 into master-2.7.4
| | |\  
| | |/  
| |/|   
| * | 4d39417 (release/8.1.1) bugfix 3
| * | 53c844d bugfix 2
| * | cc62e0d bugfix 1
|/ /  
* | 031e952 Preparing for 8.1.1-SNAPSHOT development
| * 4eabf5e Release for 7.8.1
|/
|

FAQ

Reference

results for ""

    No results matching ""