如何在Git Cherry-Pick时保留合并提交的分叉历史结构?
如何在Git中保留合并提交的分叉历史进行Cherry-Pick?
问题描述
我想cherry-pick一段包含合并提交的提交范围,当前执行cherry-pick后,合并提交会被线性应用,但我希望保留它的分叉形式,以便查看该合并提交的父提交。因为cherry-pick生成的线性历史满足不了需求,想知道能不能在cherry-pick时保留分叉历史;如果不行,Git里有什么替代方案?
使用的命令
git cherry-pick (commit C hash)~1..(commit F hash) # 当前HEAD指向test1
历史对比
当前历史
A--B--C--E--F--K (master) \ \ / J D (test2) (test1)
Cherry-Pick后的实际历史
A--B--C--E--F--K--T (master) \ \ / J D (test2) \ C \ D \ E \ F (test1)
期望的历史
A--B--C--E--F--K--T (master) \ \ / J D (test2) \ C / \ D E \ \ \---F (test1)
解决方案
1. 普通Cherry-Pick无法保留分叉历史
git cherry-pick的核心逻辑是提取单个提交的变更内容,将其作为新的线性提交应用到目标分支,它不会复刻原提交的分支拓扑结构。所以直接使用范围cherry-pick无法生成你需要的分叉历史。
2. 手动复刻分支结构并合并(推荐)
要保留合并提交的分叉形式,需要手动重建对应分支结构,再执行合并:
步骤1:基于提交B创建临时分支
git checkout test1 git checkout -b temp-branch <B的哈希值>步骤2:分别Cherry-Pick非合并提交
先在temp-branch上应用提交C:git cherry-pick <C的哈希值>创建临时分支复刻原test2的D提交:
git checkout -b temp-test2 temp-branch git cherry-pick <D的哈希值>回到temp-branch应用提交E:
git checkout temp-branch git cherry-pick <E的哈希值>步骤3:执行合并复刻原合并提交F
将temp-test2合并到temp-branch,可复用原合并提交的信息:git merge temp-test2 -m "<原合并提交F的提交信息>"此时temp-branch上的合并提交就会和原F的分叉结构一致。
步骤4:合并到test1并清理临时分支
git checkout test1 git merge temp-branch git branch -D temp-branch temp-test2
3. 可选简化方案:git rebase --preserve-merges
如果原分支结构简单,且test1分支未推送到远程,可以尝试用rebase保留合并结构,但需谨慎调整参数避免引入多余提交:
git checkout test1 git rebase --preserve-merges --onto test1 <C的哈希值>~1 <F的哈希值>
该命令会尝试复刻从C到F的分支拓扑,但需要确保参数精准,否则可能出现历史混乱。
内容的提问来源于stack exchange,提问作者alex_121
相关产品推荐
相关产品推荐

