Git Flow工作流实战指南从分支管理到发布流程的完整实践
Git Flow搞崩了我的发布流程
昨天差点被Git Flow给搞疯了。本来想用这个工作流规范一下团队的开发流程,结果发现自己对分支管理的理解还是太浅了。折腾了一整天,最后才算把发布流程理顺。
问题的起因是这样的:我按照教程创建了feature分支,然后开发完合并回develop,看起来都挺正常的。但是到了发布阶段,master分支和develop分支的数据居然对不上,而且hotfix分支合并回来的时候还冲突了一堆文件。当时我就懵了,这到底哪里出问题了?
分支命名搞乱了发布脚本
最开始我以为是合并策略的问题,折腾了半天merge和rebase的区别。结果后来发现根本不是这个问题,而是分支命名规范没统一。我的发布脚本是根据分支名称来判断当前环境的,结果团队里有人用了 feature/user-authentication,有人用了 feature/userAuth,导致自动化部署识别不出来。
这里我踩了个坑,之前觉得分支命名不重要,反正能看懂就行。结果在Git Flow这种复杂分支体系下,命名规范直接影响到自动化流程的执行。后来我重新整理了分支命名规则:
- feature/功能描述(如:feature/user-login)
- release/v版本号(如:release/v1.2.0)
- hotfix/修复描述(如:hotfix/login-bug)
Release分支的合并时机是个技术活
折腾了半天发现,Release分支的操作时机特别关键。我之前的理解是功能开发完了就可以建release分支,但实际上应该是在develop分支上的所有功能都测试通过后再创建。不然的话,还没完成的功能就被提前打包了。
另外还有一个重要的地方,Release分支创建后需要同时更新两个地方:master分支和develop分支。我当时只合并到了master,结果develop分支上还是旧的代码,新功能开发的时候就混乱了。
完整的Release流程应该是这样的:
# 1. 从develop分支创建release分支
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0
# 2. 在release分支上进行版本号更新、bug修复等发布前准备
# 修改package.json版本号等
# 3. 提交release分支
git add .
git commit -m "Prepare for release v1.2.0"
git push origin release/v1.2.0
# 4. 合并到master并打标签
git checkout master
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin master --tags
# 5. 同步回develop分支
git checkout develop
git merge --no-ff release/v1.2.0
git push origin develop
# 6. 删除release分支
git branch -d release/v1.2.0
这个流程看起来复杂,但其实每一步都有其必要性。第5步同步回develop分支特别容易忘记,我第一次就漏了这步,结果下一次从develop拉取的新feature分支就包含了还未发布的功能。
Hotfix分支处理线上紧急问题
真正的考验来自Hotfix分支。上周五晚上有个严重的登录bug需要紧急修复,我赶紧创建了hotfix分支。但是这里有几个需要注意的地方:
首先,hotfix分支必须基于最新的master标签创建,不能基于develop分支。我当时直接从develop拉了分支去修复bug,结果发布的时候发现master上根本没有这次修复。
其次,hotfix分支修复完成后需要同时合并到master和develop,顺序也有讲究。先合并到master发布,再合并到develop确保代码同步。如果顺序颠倒了,可能会影响其他正在开发的功能。
# 基于最新tag创建hotfix分支
git checkout master
git pull origin master
git checkout -b hotfix/critical-login-bug
# 修复bug后提交
git add .
git commit -m "Fix critical login bug"
# 合并到master并发布
git checkout master
git merge --no-ff hotfix/critical-login-bug
git tag -a v1.2.1 -m "Hotfix: critical login bug"
git push origin master --tags
# 同步到develop
git checkout develop
git merge --no-ff hotfix/critical-login-bug
git push origin develop
# 清理hotfix分支
git branch -d hotfix/critical-login-bug
团队协作中的权限控制问题
还有一个头疼的问题是权限控制。我们用的是GitLab,一开始所有人都可以往master和develop推代码,结果有一次误操作直接把有问题的代码推到了master。后来我设置了protected branches,限制只有特定角色才能合并到主分支。
但这里又有新的问题:PR/MR的合并审批流程。我们在GitLab里设置了至少一个reviewer批准才能合并,但有时候关键人员不在,紧急修复就卡住了。最后我们约定了一些特殊情况下的处理方式,比如紧急bug修复可以让运维直接合并。
自动化构建脚本踩坑记录
为了减少人为错误,我写了几个自动化的构建脚本。但是遇到了一个坑:不同分支的构建命令不一样。develop分支需要跑测试,master分支需要压缩资源,release分支需要生成构建报告。最初我把这些逻辑都写在了一个脚本里,用分支名称来判断执行哪个流程,结果各种if-else嵌套,维护起来特别麻烦。
后来改成根据不同分支触发不同的构建任务,每个任务职责单一:
#!/bin/bash
# build-develop.sh
if [ "$CI_COMMIT_REF_NAME" == "develop" ]; then
npm run test
npm run build:dev
fi
# build-release.sh
if [[ $CI_COMMIT_REF_NAME == release/* ]]; then
npm run build:prod
npm run generate-report
fi
# build-master.sh
if [ "$CI_COMMIT_REF_NAME" == "master" ]; then
npm run build:prod
npm run deploy:production
fi
这样虽然脚本多了几个,但是逻辑清晰,出问题也容易定位。
监控分支状态的小工具
经常会出现分支忘记删除或者本地分支和远程不同步的情况。后来我写了一个简单的shell脚本来清理无用的本地分支:
#!/bin/bash
# clean-branches.sh
git fetch --prune
git branch --merged | grep -v "*|master|develop" | xargs -n 1 git branch -d
这个脚本会删除已经合并到主分支的本地分支,避免本地分支越来越多。不过使用前一定要确认分支确实可以删除,不然可能会误删还在开发中的功能分支。
回滚机制要提前规划好
最让我紧张的一次是发布后发现数据库迁移脚本有问题,需要紧急回滚。这时候才意识到回滚机制的重要性。如果每个版本都有对应的tag,并且CI/CD流程支持按tag部署,回滚就变得很简单了。
我们的回滚流程现在是这样的:
- 查看可用的发布标签:
git tag -l - 选择上一个稳定版本进行部署
- 在GitLab中创建hotfix分支修复问题
- 重新走发布流程
这个流程比直接在master上修改要慢一些,但是更安全,也更容易追溯问题。
总结
经过这一系列的折腾,现在我们的Git Flow流程算是比较稳定了。主要的经验教训是:流程规范化比技术本身更重要,团队成员都需要熟悉整个流程,自动化脚本要简单明了,异常情况要有预案。
现在回想起来,Git Flow的核心其实不复杂,就是分支管理的规范,但是要在团队里真正落地,还需要考虑很多实际情况。比如紧急发布流程、权限控制、自动化构建等等。
以上是我踩坑后的总结,如果你有更好的Git Flow实践经验欢迎评论区交流。

暂无评论