如何将feature分支的Fix提交迁移至master且不影响后续分支合并?
好问题!首先得澄清一个Git的核心规则:提交的SHA值不可能在不同父提交下保持一致——因为Git计算SHA时会包含父节点信息、作者/提交者数据、提交内容、提交消息等所有元数据。所以你想要的Fix'和原Fix完全同SHA是做不到的,但别担心,这根本不会影响后续的合并/变基操作,Git有一套机制能识别出这是同一个修改。
下面给你两种可行的方案,根据你是否愿意改写本地feature分支历史来选择:
方案一:保留feature分支历史,用cherry-pick迁移修复
这种方法不需要改动feature分支的原有历史,适合想保留完整提交轨迹的场景:
- 先切换到master分支,把Fix提交cherry-pick过来:
git checkout master git cherry-pick Fix # 这里的Fix可以是提交的SHA、短SHA,或者相对引用比如feature~2
执行后master分支就会变成A-B-C-Fix',虽然Fix'的SHA和原Fix不同,但两者的修改内容完全一致。
- 后续合并feature到master时,Git会自动识别出
Fix的修改已经存在于master中,不会重复应用:
git checkout master git merge feature
最终master的历史会包含一个合并提交,内容是把feature分支的D、E、G、H合并进来,而Fix的修改不会重复出现。如果想要线性历史,也可以用rebase:
git checkout feature git rebase master git checkout master git merge feature
Git在rebase时会自动跳过内容重复的Fix提交,最终得到干净的线性历史A-B-C-Fix'-D-E-G-H。
方案二:改写本地feature分支历史,得到完全贴合预期的线性轨迹
因为你的feature分支是本地的,改写历史完全安全,不会影响任何远程仓库或其他开发者。用这种方法可以得到你想要的线性最终历史:
- 先把Fix提交cherry-pick到master:
git checkout master git cherry-pick Fix
- 切换到feature分支,删除掉已经迁移的Fix提交:
git checkout feature git rebase -i E # E是Fix的父提交,也可以用相对引用比如feature~3定位
在弹出的交互式rebase界面中,找到Fix对应的那一行,把开头的pick改成drop,保存退出。这时候feature分支就变成了A-B-C-D-E-G-H。
- 最后把master分支变基到feature分支上,得到完全线性的历史:
git checkout master git rebase feature
最终master的历史会变成A-B-C-D-E-G-H-Fix',所有提交按顺序排列,且没有重复的Fix修改。
关键说明
Git是通过patch-id来识别相同修改的——只要两个提交的内容差异完全一致,不管SHA是否相同,patch-id就会一致。所以在合并或变基时,Git会自动跳过重复的修改,不会出现内容冲突或重复应用的问题。
内容的提问来源于stack exchange,提问作者Kamafeather

