老顽固、老古董,这是我对 「研发」领导最直观的理解。
在我以往工作的公司中,小的、大的(相对于小的来说),都是使用 Git 作为版本控制工具。SVN 是工作4年来第一次使用……
接触后我查了 SVN 的特点,如下:
SVN 核心特点速览
| 特点 | 说明 | 评价 |
|---|---|---|
| 单一仓库 | 所有人共享一个仓库,历史记录在服务器上 | 中心化 |
| 必须联网 | commit 必须连接服务器,断网基本废了 | 硬伤 |
| 权限控制强 | 可精确控制谁能读、谁能写、哪个目录能改 | 企业友好 |
| 分支很重 | 创建/切换分支成本高,没有 Git 那么轻量 | 不灵活 |
尽管知道了这些特点,但我依然无法理解为什么要使用它。也许是原始项目就这样了,又或许是「老古董」不会使用 Git。至于其他的如”流程固定”固定等原因,我觉得关系并不大。
让我很难受的三个痛点
1. 没有分支(像 Git 那样的本地分支)
SVN 的分支结构通常是这样的:
1
2
3
/trunk ← 主干(所有人在这开发)
/branches ← 分支(很重,很少用)
/tags ← 标签
问题在于:
- X 没有像 Git 那样的轻量级本地分支
- X 不能在本地随意创建/切换分支
- X 所有开发都在
/trunk上,代码混杂
Git 的工作流
1
2
3
4
5
# Git:轻松创建特性分支
git checkout -b feature/payment
# 开发... commit... 测试... 合并
git checkout main
git merge feature/payment
Git 的三种核心工作方式:
| 方式 | 说明 | 使用场景 |
|---|---|---|
| 工作区状态 | 工作区修改,满意后 add 到暂存区 |
日常调试 |
| Stash 储藏 | 将变更”暂存”起来,稍后恢复 | 临时切换任务 |
| 分支 | 不同功能创建不同分支,互不干扰 | 功能开发 |
SVN 的问题
“毫无优势。”
- X 没有工作区状态:代码改动了,没有状态区分。A功能完成70%,要优化只能在工作区修改,出问题无法回退到70%节点
- X 没有隔离:两个功能之间没有隔离,很难控制变更
- X 无法恢复:AI改坏代码后,无法恢复之前已处理好的代码
2. 没有版本管理(代码管理混乱)
其实项目就没有版本。app端有版本,但是H5端没有,项目里的 version 字段仅仅是一个字符串,没有实际意义,你可以填 1.1.1 可以填 2.2.2,而且代码通常是在各个项目之间互相拷贝的,所以也没有版本管理。
需求上的版本,也没有实际作用,流程上没有需求的发布节点。所以就是1.1.2给甲开发,1.1.3给乙开发,乙先完成了,先发布。或者是两个功能同时发布。
在代码中的管理就非常随便了,可以说是没有版本管理。
多环境代码关联问题
开发中遇到的代码变更,做版本管理的,通常涉及到三个阶段之间的关联:
| 环境 | 用途 |
|---|---|
| 正式环境 | 线上用户访问 |
| 测试环境 | 测试人员验证 |
| 开发环境 | 开发人员编写 |
Git 的版本管理策略
场景1:线上环境出 Bug
1
2
main (线上) ──→ fix-branch ──→ release/test ──→ main
(修复) (测试) (上线)
流程:
- 从
main拉取fix分支 - 在
fix分支修复 - 合并到
release分支给测试 - 测试通过后合并到
main
优势:不影响测试环境和开发环境的代码
场景2:测试环境出 Bug
1
test ──→ fix-test ──→ test
流程:
- 拉取
fix-test分支 - 修复完成后合并到
test
优势:不影响正式环境和开发新功能的环境
场景3:开发环境
- 不同开发人员在各自分支上开发
- 开发完成后合并到主开发分支
- 不影响任何环境的代码
测试环境,在线上bug修复后,将修复后的代码合并到测试环境的分支上,就保证了测试环境的代码和线上环境的代码是一致的。
开发环境,在测试结束后,将测试环境的代码合并到开发环境的分支上,就保证了开发环境的代码和测试环境的代码是一致的,开发分支的代码是最全的。
SVN 的问题
没有版本管理,全都在那个 「碗」里操作。
典型问题场景
| 场景 | 问题描述 |
|---|---|
| 线上 Bug 修复 | 修改代码后打包发布,是否提交到 SVN 看个人。同事修复后提交,你就能拿到新代码;没提交,你的功能依然有 Bug |
| 同事协作冲突 | A 同事优化支付功能(未提测,已提交 SVN),你修复线上支付 Bug,A 提醒你不要拉取代码,改完直接打包发布 |
| 多需求并行 | 线上 Bug 改动 + 新需求改动混在一起,不能拉取/推送代码(因为A同事在优化支付功能,我拉取了,我这边的支付就有问题) |
我当时的心态已经不能简单的用「无语」来形容了…**
3. 不做 CI/CD(纯人工部署)
SVN 也支持 CI/CD,但是没有做,估计是「难做」的原因。所有人都提交到同一个地方,经常发生变更,很难做。
所以现在的项目还在使用那种人工打包的方式部署,而且是非常非常的乱。
「修改代码10分钟,部署1小时」**
SVN 的部署流程
1. 源代码地址
源代码都在 trunk 目录下,例如:
1
/trunk/xxx/slct-mini ← 「烧腊餐厅」H5项目
槽点:
- 使用汉语拼音首字母作为项目名称
- 明明是 H5,却用了
mini- 目录结构式,不像 Git 仓库,有仓库介绍等
- 项目里没有 README.md 文件,你根本不知道这个项目是做什么的
2. SVN 地址(静态资源 vs HTML 分离)
静态资源目录:
1
2
3
4
5
6
xxx/style/
├── a/pay/ ← 项目A的支付功能CSS
├── a/order/ ← 项目A的首页CSS
├── b/ ← 项目B
├── c ← 项目C
└── d ← 项目D
HTML 文件目录:
1
2
3
4
5
xxx/view/
├── a/active/new-year.html ← 项目A的新年活动页
├── b/ ← 项目B
├── c ← 项目C
└── d ← 项目D
部署时需要分别部署静态资源和 HTML 文件**
3. 部署流程(纯人工)
流程特点:
- 像「树」一样分叉:一边是测试,一边是线上
- 前端随时部署,测试完前端继续跟进
- 没有任何严谨性可言
正常流程:
- 前端打包生成
dist目录1 2 3 4
dist/ ├── css/ ├── js/ └── index.html
- 拷贝文件
css/、js/→/部署/xxx/style/a/index.html→/部署/xxx/view/a/
!!! 混乱的特殊情况:
| 情况 | 描述 |
|---|---|
| 公共页面 | 支付页面在 trunk/xxx/h5-common,但 a 目录下也有。部署到 /style/h5-common 和 /view/act,没有文档说明 |
| 伪公共页面 1 | b 项目的 order 功能,代码在 a 目录,部署到 /style/h5-common。有时部署到 /view/act,有时到 /view/b |
| 伪公共页面 2 | c 项目的 new-year 活动,代码在 a 目录,但部署到 c 自己的目录下 |
| 某些私有页面 | rank 功能,代码在 a 或 d 或 d2 目录,部署到 /view/d 和 /style/d |
最大痛点:源代码目录、部署目录的对应性没有规范**
又是公共的,又是私有的,打包命令还存在差异。
「修改代码10分钟,部署1小时」**
打包会打错,部署会部署错,我已经吃过这个亏了。
Git 的优势
1. 项目介绍清晰
在 Gitee 或 GitHub 创建仓库时:
- 有「仓库介绍」
- 通过介绍可以了解项目基本情况
- 不会像 SVN 一样对着文件夹发呆
2. 部署流程清晰
基于分支的部署:
- 手动和自动都类似
- 线性部署,不会都由前端打包
- 可控性强
测试环境手动部署:
1
前端打包 → 发给测试 → 测试部署 → 测试通过 → 部署线上
为什么不是前端部署测试环境?**
测试通过后部署线上,不能保证线上的 dist 是测试通过的 dist。
自动部署(主流):
- 使用
Jenkins - 前端提供打包命令
- 代码合并到
test分支 - 自动部署或测试手动点击
流程清晰:
1
2
3
开发 → 提交到 test 分支 → 自动部署测试
↓
测试通过 → 合并到 main 分支 → 自动/手动打包上线
职责清晰:前端只负责代码开发,不需要关注部署问题。
总结
| 维度 | SVN | Git |
|---|---|---|
| 网络依赖 | 必须联网 | 本地可工作 |
| 分支管理 | 笨重 | 轻量灵活 |
| 合并冲突 | 困难 | 相对容易 |
| CI/CD 支持 | 困难 | 成熟完善 |
| 权限控制 | 精细 | 较粗粒度 |
最终建议
新项目强烈建议用 Git**
SVN 只建议在以下情况使用:
- 遗留项目无法迁移
- 企业有强合规要求
- 团队完全无法接受 Git 的学习成本
很遗憾的是,连让测试规范下bug的描述的建议都没有得到重视,别说这种部署流程了。
本文基于个人真实工作经历,让人感到非常无语的经历,仅代表个人观点。