使用 cherry-pick 解决相互依赖的PR之间的拆分问题
🏒

使用 cherry-pick 解决相互依赖的PR之间的拆分问题

Tags
git
description
更新时间
Last updated March 9, 2023
 

背景

我们期望PR越小越好,这样方便 review ,节省时间和心智负担,同时也能明确每个 PR 的用处,在回顾提交记录,回滚问题代码的时候都会更加有效。
 
我们划分 PR 的节点很明确,最小就一行代码,修复一个 bug,完成一个功能点,一个 PR 的最大行数不是一个固定值,但是从指导意见来说,剥离掉那些 swagger 更新,配置数据,graphql query 等等,一个 PR 的逻辑代码行数不应该超过 400 行。
 

PR 相互依赖的问题

PR 的相互依赖是 PR 过大的关键
在日常的 bug fix,小功能开发上,我们基本都能做到不超过 400 行,因为功能本身的代码总行就不会太多,容易出现 PR 过大的问题时,往往都是在大需求的开发上,尤其是比较紧急的时候,为了快速开发,我们往往会用一个 PR 实现所有的需求。原因也很简单,一个大的需求,他的功能往往是互相关联的。
比如我要开发详情页,我就得有列表页来点击进入详情,有时候他们之间的代码还可能是复用的,所以如果要拆分PR,就会导致这些 PR 之间是相互依赖的,那么如果需要等待上一个功能的 PR review 完才能开始下一个就会大大降低开发的效率。所以导致我们此时更加愿意选择将所有代码堆在一个 PR 里面。
 
所以我们得解决相互依赖的 PR 之间如何处理的问题。
上面是我们最初是的一个场景,
notion image
 
在这里, PR2 拥有 PR1 的部分 commit ,但是在 RP1 合入 master 之后,PR2 想要 rebase master 是会出错的,因为 rebase 会逐个比较 commit, b0 和 a1 的比较,他们的代码差别可能是很大的,这就导致了冲突。
另外即使解决完冲突,最终 PR 会包含3个 commit (a1, a2, a3)的代码,而我们其实只希望有 PR2 相对 PR1 新增的代码,也就是 a3 的代码,所以这种直接合入的方式是不可行的。
要解决这个问题我们需要掌握几个 git 知识点。
 

reflog

git reflog 是一个神器,可以查看你之前所有的操作和他们对应的 hash
有了 reflog,你的任何代码基本上不可能丢失。
比如说我有一个 branch 不小心删除了,我可以用 git reflog 查看之前的记录,找到那个 branch 对应的记录,就可以用 git refloggit switch -c [new-branch] [commit-id] 恢复对应的 branch
 

reset

reset [hash] 可以把当前分支直接指向到某个提交。
默认是 reset —soft ,他会保留 reset 导致的文件修改。
reset —hard 就是跳转过去,不保留 reset 导致的文件修改。
注意,我们可以指向任何分支的提交,并非只有当前分支的。例如我们可以直接从 PR
 
 

cherry-pick

notion image
git cherry-pick [hash] 是把某一个 commit 拿过来
git cherry-pick [hash1]..[hash-n] 是把 hash1 到 hash-n 之间的提交拿过来,但是不包括 hash1
所以我一般用 git cherry-pick [hash1]@^..[hash-n] ,这样可以把包括 hash1 的若干个提交都拿过来。
使用的时候可能有时候会担心会不会造成什么别的问题,但是实际上大部份时候都不会有问题,最多是出现冲突。只需要解决冲突。
 

开发流程

了解了这三个命令之后,我们就可以开始了。
notion image
notion image
notion image
notion image
⚠️
注意,使用这种方法的时候最好把 commit 写清楚,这样才能看出来哪些提交属于哪个功能的代码,如果全部都是 update code,那根本没办法知道要 cherry-pick 哪些 commit
你也可以参考别的规范:

总结

我们可以通过 reflog 找到任意 commit 的记录,保证自己不丢失任何的 commit
我们可以通过 reset --hard 跳转到任意 commit ,包括不同的分支。
我们可以通过 cherry-pick 把一系列 commit 摘到另一个 commit
我们可以通过 reflog reset cherry-pick 之间的组合解决几个相互依赖的PR如何拆分的问题。
 
其实本质就在于我们需要去多理解和尝试 git 的一些命令
当明确 git 的一些核心概念之后,我们其实可以更加 “大胆” 一点,不用畏手畏脚的,在明确自己要做什么的基础上,多尝试这些命令。反正 commit 是基本不可能丢失的.