你真的理解Git分支操作了吗?记一次线上问题的追溯和解决

744 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

前言

Git、SVN等版本管理工具是日常开发工作中的重要生产力工具。然而,你真的理解Git分支操作了吗?代码管理出现问题了,又该如何追溯和解决问题呢?本文将详细介绍一次线上问题的追溯和解决的过程。

早上,产品和测试同事反馈:怎么线上的某个页面的功能突然发生异常了,而且还没上线的功能怎么出现在页面上了?是不是昨晚的发版出问题了?

不应该啊,昨天发版没有改到这个页面的代码合代码也只合了对应的开发分支,应该没问题呀...

由于是生产环境的问题,我赶紧看看是什么原因引起的。直觉就是,开发分支的代码合到生产分支时出现问题了。

问题追溯

使用Git Graph查看代码提交记录,各个提交的代码看了下,咋一看是正常的,都是新功能相关的代码。仔细一看,才发现端倪:最新的master分支竟然包含了uat分支的代码!

问题重现

为方便重现问题,这里新建了一个demo仓库,代码提交也简化了,只保留了与问题相关的几个提交。

代码提交记录如下所示:

git-commit-log

可以看到,在dev分支上,开发者gittig11有2个提交,提交的最终代码是:

git-commit-1

开发者user有一个提交,新增代码是新功能1相关的,也没有问题:

git-commit-3

不过仔细一看,可以看到uat分支和dev分支交叉了,而且还多了一个提交,内容是Merge branch 'dev' of https://github.com/gittig11/git-branch-demo into dev。查看这个提交,内容如下:

git-commit-2

在开发者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-actions

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测试环境分支,包含了各种需求的代码,未发版到生产环境的内容都可以发上去测试。
回归环境regressionuat通过后回归测试。
预生产环境release(保护分支)做线上数据测试。
生产环境master(保护分支)生产环境分支。

Git 提交规范

  • 代码提交时注释内容不能为空。

  • 注释的内容应当清晰、简洁,包含两部分内容:第一是本次操作的类别:feat/fix等;第二是文字性的描述,简要讲解实现的功能或修复的解决方案。如:feat:xxx页面开发

  • 类别说明

feat: 添加新特性

fix: 修复bug

docs: 仅仅修改了文档

style: 仅仅修改了空格、格式缩进、都好等等,不改变代码逻辑

refactor: 代码重构,没有加新功能或者修复bug

perf: 增加代码进行性能测试

test: 增加测试用例

chore: 改变构建流程、或者增加依赖库、工具等

参考