myblog
myblog copied to clipboard
随手笔记:cherry-pick 实现跨仓库合并代码
场景
在一个需求中用同一个脚手架创建了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仓库,这显然不是我们要的结果。
正好用到,感谢