Git cherry-pick后再merge出现一个“奇怪”的现象

本文探讨了使用Git的Cherry-Pick命令从主分支选择特定提交应用于功能分支时遇到的问题。当后续需要将功能分支合并回主分支时,可能会出现重复提交的情况。文章分析了这种现象的原因,并提出了相应的解决思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景描述:有的时候基于一个master branch拉出一个独立feature分支做开发时,两条分支都在并行开发,如果master分支增加了某些功能,解决了某些关键bug,而独立feature分支不需要所有的增加的commit,只需要某一笔的修复,此时首先想到的就是单独cherry-pick该笔commit,然而后续如果再次将该feature merge回master,“奇怪”的现象发生了….

举例说明:

git仓库以ngnix代码为例,不知道什么时候clone的代码,分支还在unstable branch上。。。

  • 以unstable分支为基础checkout一个test1分支。
  • 在unstable分支上提交一笔commit bb3200604fcd3cefe26fb23bd6747f5563f514ac
  • 在test1 branch上cherry-pick该笔commit,commit id为9b97d6038a14e348f50a7b44f2a0a29af54aa820
  • 回到unstable分支,merge test1 branch,出现下面的现象:

    unstable分支merge test1 branch后的graph线路图

为什么感到”奇怪“
  • 起初我的想法时merge合并后,不会出现merge commit,也只会存在同样的一笔commit,这样看起来会很清爽,而如果出现两笔一模一样的commit,看起来会很疑惑。虽然代码没有任何问题,而且如果在提交多笔commit后再merge,大部分人都不会主要到这个现象,所以应该很少人主要到这个“问题”。
  • 由于个人多少对代码有点洁癖,当发现这个现象时蛮奇怪的,为什么git不能智能记录两个branch cherry-pick的过程,在merge时只保留一个(最好是master branch上的)commit?(这点是完全可以做到的啊),不过事实就是目前的状态了。
为什么会这样?
  • cherry-pick在Git中的处理应该只是将一个commit的修改重新add, commit,push到另一个branch上,并没有记录之间的关联。
  • 当merge时,认为另外一个branch只是做了完全相同的修改,并没有冲突,所以完整的保留两个branch上的commit。
后续如何处理
  • 虽然以上的解释很充分,原理上完全没有问题,不过对于这样的两笔一模一样的commit,感官上还是不爽的,所以我决定尽量不在需要merge回去的branch上cherry-pick父branch上的commit了。
Git 中,`git merge` 和 `git cherry-pick` 是两种用于整合分支更改的命令,但它们的应用场景和行为存在显著差异。 `git merge` 用于将一个分支的所有更改合并到另一个分支上。它会创建一个新的合并提交(merge commit),记录两个分支的历史交汇点。这种操作保留了完整的提交历史,适用于需要将整个功能分支或发布分支合并到主分支的情况。例如,在开发完成后将特性分支合并到 `main` 或 `develop` 分支时,通常使用 `git merge`。如果合并过程中出现冲突,Git 会提示用户手动解决,并通过 `git add` 标记已解决的文件后继续合并过程[^2]。 相比之下,`git cherry-pick` 允许开发者从其他分支中选择特定的提交(commit)应用到当前分支上。这种方式不会合并整个分支的历史,而是仅复制指定提交的更改内容(即补丁),并在当前分支上生成新的提交。这对于将某个修复提交从发布分支快速应用到开发分支非常有用。例如,当发现一个紧急 bug 修复已经提交到生产环境分支,但尚未合并到开发分支时,可以使用 `git cherry-pick` 将该提交单独引入开发分支。与 `git merge` 不同的是,`git cherry-pick` 不会生成额外的合并提交,且保留原提交的提交信息(message),但其提交哈希值会发生变化[^4]。 此外,两者在处理冲突的方式上也有所不同。`git merge` 在遇到冲突时会暂停合并过程,让用户逐一解决冲突并标记为已解决(`git add`),然后继续合并;而 `git cherry-pick` 同样会在冲突时暂停,要求用户解决冲突后执行 `git cherry-pick --continue` 来完成提交[^1]。 总结来看: - **适用场景**: - `git merge`:合并整个分支的更改。 - `git cherry-pick`:只合并某些特定提交的更改。 - **提交历史影响**: - `git merge`:保留完整的历史,并生成一个新的合并提交。 - `git cherry-pick`:仅复制选定提交的更改,不包含原始提交历史。 - **冲突处理流程**: - 两者都需要手动解决冲突,但 `git merge` 更适合处理大规模合并中的冲突,而 `git cherry-pick` 更适合精细控制单个提交的合并过程[^3]。 ### 示例:cherry-pick 多个提交 ```bash # 拾取多个独立提交 git cherry-pick abc123 def456 # 拾取某个范围内的提交(不包含 abc123) git cherry-pick abc123..def456 # 拾取包含某个提交及其之后的所有提交 git cherry-pick abc123^..def456 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值