myblog icon indicating copy to clipboard operation
myblog copied to clipboard

随手笔记:cherry-pick 实现跨仓库合并代码

Open lihongxun945 opened this issue 2 years ago • 1 comments

场景

在一个需求中用同一个脚手架创建了4个不同的模块A、B、C、D,在写代码的时候过程中发现脚手架年久失修,里面的部分配置有问题,我就在A模块中提交了一个 Fix修复了错误的配置,这个时候B、C、D模块已经由外包同学写完了静态样式并提交了,此时提交状态如下图所示(为了方便省略了CD模块):

提交历史

作为一个有“一点点追求”的程序员,显然不能容忍到处复制粘贴代码的行为。那么此时除了手动复制代码外,如何把这个Fix应用到其他三个模块中呢?

跨仓库 cherry-pick

合并指定的一些提交到当前分支,可以用 cherry-pick 命令,为了实现在B仓库中合并A仓库的变更,首先需要让B仓库能读取到A仓库的提交记录,只需要B仓库中添加A仓库为远程仓库即可,然后拉取A仓库的提交记录,在B仓库中执行此命令:

git remote add fix {仓库A的地址}
git fetch fix

然后就可以看到 fix/daily/0.0.1 分支中存在我们的提交:

提交日志

再执行 cherry-pick 即可合并到 B模块:

git cherry-pick a514c5

此时提交记录变成下图这样,其中Fix1虽然和 Fix的ID不同,但是其中的修改内容是一样的

提交记录

同样的方式,可以用三个命令就把C、D模块的配置也修复。

什么情况下适用?

同一个仓库一般不会出现问题,跨仓库的情况下合并,只有当被更新的文件在两个仓库中是相同的结构时才可行,否则会出现很难修复的冲突,还不如手动复制代码。在这个场景中因为都是用同一个脚手架创建的模块,有着相同的文件结构,所以才可行,如果是两个完全不同结构的仓库,更新的文件没有对应关系,不建议这么操作。

为啥不能直接 merge?

有好奇的小伙伴可能会问最后一步用 git merge a514c5 可以么? 答案是不行。这是两个命令的解释:

cherry-pick: Apply the changes introduced by some existing commits. merge: Incorporates changes from the named commits (since the time their histories diverged from the current branch) into the current branch.

最大区别在于:cherry-pick 只合 commits 中变更, 而 merge 会把历史上所有不同的 commits 全部合并。对于现在的场景,由于 AB两个仓库的所有提交都不同,也就意味着会把 A1->A2->A3-Fix 这4个提交的变更全部合并到B仓库,这显然不是我们要的结果。

lihongxun945 avatar Jan 17 '23 06:01 lihongxun945

正好用到,感谢

kmq116 avatar Jan 31 '23 05:01 kmq116