一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
前言
Git、SVN等版本管理工具是日常开发工作中的重要生产力工具。然而,你真的理解Git分支操作了吗?代码管理出现问题了,又该如何追溯和解决问题呢?本文将详细介绍一次线上问题的追溯和解决的过程。
早上,产品和测试同事反馈:怎么线上的某个页面的功能突然发生异常了,而且还没上线的功能怎么出现在页面上了?是不是昨晚的发版出问题了?
不应该啊,昨天发版没有改到这个页面的代码,合代码也只合了对应的开发分支,应该没问题呀...
由于是生产环境的问题,我赶紧看看是什么原因引起的。直觉就是,开发分支的代码合到生产分支时出现问题了。
问题追溯
使用Git Graph查看代码提交记录,各个提交的代码看了下,咋一看是正常的,都是新功能相关的代码。仔细一看,才发现端倪:最新的master分支竟然包含了uat分支的代码!
问题重现
为方便重现问题,这里新建了一个demo仓库,代码提交也简化了,只保留了与问题相关的几个提交。
代码提交记录如下所示:
可以看到,在dev分支上,开发者gittig11有2个提交,提交的最终代码是:
开发者user有一个提交,新增代码是新功能1相关的,也没有问题:
不过仔细一看,可以看到uat分支和dev分支交叉了,而且还多了一个提交,内容是Merge branch 'dev' of https://github.com/gittig11/git-branch-demo into dev。查看这个提交,内容如下:
在开发者user提交的代码上面还有一行:这是不能发版的内容!
定位原因
为什么会出现这样的问题呢?
查看代码提交记录,我们可以看到在分支交叉的地方,dev分支是基于uat分支的,而且开发者user在本地新建了一个dev分支,再关联远程的dev分支拉取最新代码。
问题就出在这里,开发者user拉取代码时,先在本地新建了一个dev分支时,此时没有先切换到master分支,而是处于uat分支上,这样,新建的dev分支是基于uat分支的!之后提交代码时,会不知不觉中把uat的代码合到dev分支中...
找开发者user验证一下,果然是上面这样操作的,那么我们就确定引起问题的原因了。
问题解决
找到原因了,我们赶紧开始回退代码。
对于dev分支:
git reset --hard xxx # 回退代码
git cherry-pick A..B # 转移从 A 到 B 的所有提交, 如果要包含提交 A,可以使用 git cherry-pick A^..B
git push -f # 更新代码
对于master分支:
git reset --hard xxx # 回退代码
git push -f # 更新代码
# 合并分支并提交代码
git merge dev
git push
然后,联系运维大佬、项目、产品等,紧急发版修复问题。
PS:在拉取新分支的时候,我们要注意的是,要先切换到master分支再进行操作!
// 正确的做法
git checkout master # 切换到master分支,这一步很重要!
git checkout -b dev # 新建分支
git pull origin dev # 关联远程分支、获取更新
// 或者
git pull # 拉取更新
git checkout dev
经验总结
加强代码评审
通过加强 code review,可以发现代码中潜在的问题,更重要的是有助于提升代码质量。不过,像开发分支的代码污染这种问题还是有点防不胜防... 因此,开发人员加强Git版本管理意识并严格遵守Git操作规范,就显得尤为重要了!
Git 原理
Git 操作示意图如下所示:
Git 分支操作
// 查看本地分支
git branch
// 查看所有分支
git branch -a
// 切换分支
git checkout dev
// 新建分支
git checkout -b dev
// 删除本地分支
git branch -d dev
git branch -D dev // 可以在不检查merge状态的情况下删除分支
// 删除远程分支
git push origin --delete dev
// 本地分支重命名
git branch -m oldName newName
git push origin newName
// 合并分支
git checkout master
git merge dev
Git 分支规范
| 环境 | 分支 | 说明 |
|---|---|---|
| 开发分支 | feature/* or hotfixes/* | 功能开发分支,先建立Issue再根据功能 (feature/ * ) 或者bug修复类型 (hotfixes/*) 命名。 |
| UAT环境 | uat | 测试环境分支,包含了各种需求的代码,未发版到生产环境的内容都可以发上去测试。 |
| 回归环境 | regression | uat通过后回归测试。 |
| 预生产环境 | release(保护分支) | 做线上数据测试。 |
| 生产环境 | master(保护分支) | 生产环境分支。 |
Git 提交规范
-
代码提交时注释内容不能为空。
-
注释的内容应当清晰、简洁,包含两部分内容:第一是本次操作的类别:feat/fix等;第二是文字性的描述,简要讲解实现的功能或修复的解决方案。如:
feat:xxx页面开发。 -
类别说明
feat: 添加新特性
fix: 修复bug
docs: 仅仅修改了文档
style: 仅仅修改了空格、格式缩进、都好等等,不改变代码逻辑
refactor: 代码重构,没有加新功能或者修复bug
perf: 增加代码进行性能测试
test: 增加测试用例
chore: 改变构建流程、或者增加依赖库、工具等