「转」化繁为简的企业级 Git 管理实战(三):分支管理策略

本文将简单讨论下我们在开发过程中尝试的各种分支管理策略,在面对各种复杂场景下呈现的优势与不足,以及我们的妥协和后续期望。 查看原文请点击这里

说到版本控制,就不得不提到分支管理策略。就像学开车必须学学交通规则。分支管理策略是代码版本控制的基础组成部分。为团队定制一套合适的分支管理策略,就好比制定了一套合理的交通规则,可以让团队的代码的更加有序地演进,尽可能降低多分支带来的复杂度,并避免由于分支混乱引发的各种“车祸”。本文将简单讨论下我们在开发过程中尝试的各种分支管理策略,在面对各种复杂场景下呈现的优势与不足,以及我们的妥协和后续期望。

Github-Flow

作为 Github 的重度用户,我首先考虑的当然是 Github-Flow

image

Github-Flow 是一种非常简单的分支管理方案。它的流程只有如下几步:

  1. 拉出一个新分支;
  2. 在新分支上进行修改,并提交和推送你的改动;
  3. 发起一个 Pull Request ,向代码管理员申请将你提交的分支合并到原来的分支;
  4. 讨论并接受 Code Review。在这个过程中,你依然可以继续推送新的代码到你的开发分支上,并且新的提交在推送后会出现在未完成合并的 Pull Request 页面中;
  5. 合并和发布。Review 通过后,代码管理员将该分支合并到原来的主分支上。
    在 Gitlab 中同样可以使用 Github-Flow,唯一的区别是叫法从 「Pull Request」 变成了「Merge Request」 。下图是一个被成功合并的 Merge Request:


    image

Github-Flow 有如下几个让人着迷的优点:
简单好操作。只有主分支和开发分支。不像 Git-Flow 那样需要引入一堆的辅助分支。
推动 Code Review 。通过 Pull Request 的方式,使得 Code Review 成为了日常开发的必经流程,有助于。

确保可编译。所有 Pull Request 都会触发持续集成测试,只有通过测试的才允许并入主分支。这就杜绝了代码编译不过的情况。

然而,面对复杂的项目,Github-Flow 暴露出了如下的不足:

  1. 解决冲突困难。多人协作的项目难免会出现冲突,一旦遇到冲突,Merge Request 就没法被直接被合并了。这个时候只能再从目标分支拉出一个分支→合并这个分支→解决完冲突→推上远程仓库再次发起 Merge Request 。对于大多数习惯了用 Merge Request 合并分支的人来说,这个过程一下子复杂了起来。


    image
  2. Code Review 容易流于形式。虽然 Github-Flow 加入了 Code Review 的过程,但这依然取决于双方对待 Code Review 的积极性。如果没有充分的讨论代码的细节,仍然无法保证代码的质量。实际团队开发中,我们发现在线进行的 Code Review 并不如面对面讨论高效。更严重的是一旦双方没有 keep moving 的意识,大量 Merge Request 被积压,而这些 Merge Request 会不断包含新的 commit 进来,这就会使得 Merge Request 更加难以合并。
  3. 持续集成测试无法保证子模块可编译。持续集成可以作为 Merge Request 的准入条件,但这仅仅只是主工程的“福利”。而如上一篇文章所说,子模块的持续集成远比主工程复杂得多,难以直接在 Merge Request 页面中给出持续集成测试结果。而对于我们的项目,主工程基本没有多少业务代码,大部分的功能开发都是在子模块上,这就使得 Merge Request 的持续集成功能显得鸡肋了。
  4. 还有一些 Gitlab 的交互问题。在 Gitlab 中,默认的合并目标分支是 master 分支:


    image

    当你花上一分钟填完合并描述,选完指派人后,发现目标分支忘了改。此时就只能点击页面下方的 “Change Branches” 链接进入分支选择页重新选择分支。回来后你会发现你所填写的所有内容,包括指派人都被清空了:


    image
  5. 不细心的人往往没注意到这个问题,于是提交了一个没有指派人的 Merge Request ,这带来的后果是这个 Merge Request 永远没人关注和合并。

综上所述,Github-Flow 更适用于那些只以 master 分支为主分支,更注重迅速发布的简单项目。这使其非常适合用在维护 Github 上的这些「集市型」的的开源项目,而不适用于「大教堂型」的企业级项目。正如 Github 的 Scott Chancon 大神所说:

For teams that have to do formal releases on a longer term interval (a few weeks to a few months between releases), and be able to do hot-fixes and maintenance branches and other things that arise from shipping so infrequently, git-flow makes sense and I would highly advocate it’s use.
For teams that have set up a culture of shipping, who push to production every day, who are constantly testing and deploying, I would advocate picking something simpler like GitHub Flow.
Scott Chancon, Issues with git-flow
附图 1 《大教堂与集市》这本书讨论了两种软件开发模式及背后的哲学。

Git-Flow

Git-Flow 是由 Vincent Driessen 在他的一篇文章 《A successful Git branching model》 中提出的分支管理策略。

image

与 Github-Flow 相比,Git-Flow 拥有更多的分支:

  • master:可以提供给用户使用的正式版本;
  • develop:用来生成代码的隔夜版本(nightly);
  • feature:用于开发某个功能;
  • hotfix:用于修复线上代码的 bug;
  • release:用于正式发布版本前的测试分支。

Git-Flow 提出的分支管理策略完整而实用,它甚至已经成为了一个通用开发流程标准。开发者们可以在多个团队和项目中遵守同一套流程。但 Git-Flow 也不是万金油。遇到复杂的项目,它也未必能完全适用:

  1. 容易出现冲突。Git-Flow 设计了多个分支各司其职,但多分支带来的苦恼是容易出现冲突。最常见的问题是,由于我们实现了子模块 commit id 的自动更新,主分支与开发分支的子模块 commit id 经常变动,导致 develop 分支向 master 分支合并的时候出现大量冲突,阻塞发版进度。

  2. 多产品线的问题。

    我们的主工程存在多条产品线:master 分支仅仅维护一个基础模板,而 jilin 、taishan 等分支才是用于产出真正产品的分支。每条产品线的各自有一套 Git-Flow 分支体系,并用前缀区分产品线。例如 jilin 的 develop 分支就叫 jilin-dev 。而子模块既可能和主工程一样多个产品分支,也可能是一个通用模块。对于通用模块,只需要维护一套 Git-Flow 分支体系。例如 common 子模块就只有标准的 master、dev 等分支。

    对于多产品分支的主工程和子模块,当改动了某个分支的代码,你就要非常慎重的考虑这部分改动是否通用,是否需要并入其他产品线的分支。而 Git-Flow 并没有探讨多个产品线并存情况下的代码合并方案。

    对于通用的子模块,拉 release 分支时又存在「锁」的问题。比如,负责 jilin 产品线的同事即将发版,于是把 common 子模块拉出了一个 release 分支。其他产品线的同事依然可以继续为 common 子模块的 develop 分支提交 feature 。但还没等 jilin 产品线完成发版。taishan 产品线的同事也准备发版了,此时 release 分支早已经被 jilin 的同事拉出来,而这个 release 分支却没有 taishan 产品线要发版需要的 feature 。这就阻碍了 taishan 产品线的发版。

妥协与期望

为了化繁为简,我们做了些妥协:

  1. 产品线取消 develop 分支。每条产品线取消 develop 分支,并放开产品线的主分支的提交权限。这种方案大幅减少了合并冲突的苦恼,避免发版受阻,而稳定性依然可以通过 feature 分支来保证。我们相信只要日后我们的模板足够完善,产品线的开发成本会越来越低,稳定性也会越来越强。
  2. 用 cherry-pick 来同步多条产品线的代码改动。对于通用的改动,可以使用 cherry-pick 来将改动同步到其他分支上。我们扩展了 fmanager 的功能,为其实现一个 cherry-pick 命令:
    1 $ fmanager cherry-pick <commit id> <分支列表>
    例如,假如希望把 weihai 分支上的一个提交同步到其他分支,可以使用如下命令:
    1 $ fmanager cherry-pick 023e937d master,jilin,taishan
    通用的子模块发版时,始终拉出产品 release 分支。
    例如,jilin 产品线需要发版了,于是从 common 模块的 master_dev 拉出了 jilin-release 分支:
    image

    拉出分支后,与 jilin 分支有关的临时改动可以在 jilin-release 中进行。同时 common 模块依然可以给负责其他产品线的同事提交新 feature 。此时 taishan 产品线的同事如果要发版,可以拉出 taishan-release 分支:
    image

    之后,如果 jilin 产品线的同事修改了一个通用的 bug,同样可以将这个提交 cherry-pick 到其他分支:
    image

其实,与其说是 Github-Flow 和 Git-Flow 的问题,不如说是现阶段我们的产品架构的问题。用分支来实现产品线的差异化使得一个仓库出现了多个主分支,而这种复杂的模式已经超出了通用的分支管理流程所能解决的范畴。另外,现阶段子模块的不稳定也导致开发过程中不断需要跨产品线同步代码,给产品线的开发造成负担。

日后我们希望对工程的架构进行调整,通过配置文件来实现产品差异化,而不再创建产品分支。另外,子模块也会越来越稳定,可以低成本接入到各个产品线中,而不再需要频繁迭代。到了那一天,我们的项目就能够重新回归到严格的 Git-Flow ,将 化繁为简 做到极致。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249