昨天改了git flow feature的实现,提供一个选项,finish时再也不保留feature分支上的提交历史(http://www.jiangyouxin.net/2013/02/12/git_flow_1.html)。今天的主题是release分支。 html
在原版git flow的实现中,release分支与feature分支很像,都是基于develop建立,并在结束时合并回develop。所不一样的是,release分支还要合并到master分支并打TAG。注意这里的次序是合并(git merge no-ff)在前,TAG在后,这在两个方面都是有点问题的: git
(1) 若是master上,存在没有合并到develop和release分支的修改,则会有灾难性后果。
固然,若是全部开发者都严格遵照git flow的规范,这种状况不会出现;但git flow的原版中并无对此作sanity检查。在准备发布时,release分支上的代码是通过测试的,但这个代码与master(若是master有过修改)的合并结果是未经测试的。在把TAG打在合并结点上,就得保证合并先后代码是一致的,不然就有些草率了。 安全
(2) TAG是极强的标志(在gitk中有醒目的显示),足以区分版本边界;没有必要再单首创建一个merge结点。
在nvie的原文中有一句话,能够用来解释他对--no-ff的偏心:the release branch is merged into master (since every commit on master is a new release by definition, remember)
也就是说,原做者指望每一次版本发布,都在master分支上产生一个(有且只有一个)提交结点,--no-ff就是用来建立这个结点的。遗憾的是,这在SVN等线性提交的版本管理系统中成立,在git中则不成立。git中merge结点的两个父亲是对等的,整条被合并的release分支(而不只仅是最后那个合并结点)都是master分支的一部分,在这一点上,nvie画的那张图把他本身误导了: 测试
上图的master分支看上去特别干净,只有少数几个结点,每一个结点都是一个发布版本。但其实这张图里,除了develop分支最下面的那个黄色结点以外,都在master分支上。master只是一个指向最新发布版本的引用而已,要区分哪些结点表明发布版本,只能靠TAG。因此这里--no-ff是白费工夫的。 spa
在我对git flow的修改中,这里git merge的参数反过来了,用的是--ff-only。若是出现上面的状况(1),merge会失败,此时报一个错误信息来警示用户(有的时候出现这条错误信息是正常的,详见下一篇 http://www.jiangyouxin.net/2013/02/14/git_flow_3.html);若是merge成功,因为是Fast Forward,在当前位置打TAG是安全的。 .net
另外一个问题,是git flow原做者可能没有去考虑,但厂里的开发却常有的状况:release分支建立以后,由于种种缘由,该版本不须要再发布,但修改须要保留,下次发布时间再议。git flow release finish命令(git flow一个让人很不爽的地方就是命令太长)有一个参数-n(不打TAG),跟这个需求最接近。但光不打TAG不行,还得不向master合并才行。因此在个人版本中,-n的语义作了修改,至关于取消发布,release分支退化为feature分支,只向develop合并。 htm
而后就是和feature分支相似的问题了:release分支的提交历史是否须要保留?我以为大部分状况是须要保留的。release分支在版本发布以前建立,上面的提交大可能是bug fix,并且各个提交之间的关联性较小,这一点与feature分支是大不同的。git flow原版对release分支也提供了-S(squash)参数,但遗憾的是,实现也是有问题的;由于我如今也没把正确的实现写出来,这个就等之后有空再说了。 开发