记一次 git 优雅找回自己的代码
曦子最近被紧急抓到一个新的 team 做项目,新项目用的框架和开发流程跟之前的部门两个风格完全不同,这是大背景。
遇到的问题
他们有个公共分支叫 release_xxx_xxx(其实这是个仅测试分支), 这个分支上每天都有很多人提交代码, 提交方式是直接 merge 分支到 release 分支, 我有个坏习惯,合并后删除本地分支。
因为我没有提前问清楚, 结果导致我本地没有任何分支包含我之前写的代码, 也没有备份. 所以为了后续 review 合并, 需要想办法找回之前写的代码.
解决思路
这个仓库是个大仓, 好处就是我的提交基本在一个文件夹, 还有就是这里面有很多 AI 提交的代码, 所以仅根据 Author 是无法过滤自己的代码。需要通过 commiter 来过滤。同事 A 点子王率先发难: 可以直接把你的文件摘出来, 多人修改的文件注意下就行。同事 B 建议用 goland 做 diff, 直接对比两个分支的文件夹差异.
我是不乐意按文件处理的,这样很慢且容易出错。
我想了下, 既然 merge 都在 release 分支上了, 那么我可以通过 git log 找到我的 commit id, 然后 cherry-pick 到一个新分支.
具体操作
- 找到我的 commit id 列表
别问我为什么用 –no-merges.
git log release_xxx_xxx --no-merges \
--committer="username" \
--reverse \
--format="%H" \
| xargs git cherry-pick- cherry-pick 到新分支处理冲突
考虑分支多人修改, 冲突不可避免, 需要手动解决冲突. 所以我尝试了好几次都感觉有问题,因为需要找的人太多,很耗费时间,不得不想有没有更优雅的方式.
这里有个关键的点, release_xxx_xxx 分支上肯定是我的代码的最新版本, 所以我可以直接用 release_xxx_xxx 分支的代码覆盖掉冲突文件. 这里有个 git 命令可以在这个场景下方便解决冲突, 那就是 –theirs 参数, 他可以直接用目标分支的代码覆盖掉冲突文件, 不用你去人为区分, 当然, 场景不同切莫乱用。
git checkout --theirs . && git add . && git cherry-pick --continue这套流程下来, 我大概 cherry-pick 了 50 多个 commit, 仅一次需要我手动处理的冲突(编译不过).
聊聊开发流程
我之前在的项目组严格要求以下规范:
- 一个分支一个功能点
- 不允许使用 merge, 必须使用 rebase 保持提交历史线性
- 除版本发布分支外, 所有分支必须 squash commits 成一个 commit 后才能合并到主分支
- commit message 尽量 符合规范(简洁明了)
- 这里没有使用(feat|fix|docs|style|refactor|test|chore): 开头, 我觉得算是个缺点
- 代码 review 必须通过后才能合并( 2 * approve)
- 公共分支禁止直接提交代码, 必须通过 PR 合并
- 依赖代码优先合入公共分支, 公共分支即主分支, 后续开发分支基于公共分支创建, 按需合入.
而现在大家为了测试方便, 大量使用了 merge, 关键点在于自己开发分支依赖也难以处理, 需要自己假设对方的 api 设计, 或者抄过来, 我感觉这很不 git, 也很不 flow.