Git变基后丢失合并提交代码,如何正确执行变基操作?
看起来你踩了Git变基的一个常见坑:普通的交互式变基会扁平化合并提交,丢失你在合并时手动解决的冲突结果。因为git rebase -i默认会把合并提交拆成单个分支的提交,相当于重新走一遍这些提交的应用流程,而之前合并时解决的冲突不会被保留,导致你需要重新解决所有冲突,甚至因为合并提交的内容丢失而让代码彻底坏掉。
下面是两种能正确保留你合并冲突解决结果的方案,选一种适合你的就行:
方案一:用--rebase-merges保留合并结构(推荐,Git 2.18+支持)
这个选项会让Git在变基时保留原有的合并提交结构,不会扁平化分支,从而自动保留你在合并ME时解决的冲突。
步骤:
先恢复到变基前的状态
- 如果你还在变基的冲突解决流程中,直接执行:
git rebase --abort - 如果你已经完成了变基且代码损坏,用
git reflog找到变基前的分支状态(找类似checkout: moving from master to your-feature-branch或者commit: D的记录),然后重置回去:git reset --hard HEAD@{n} # 把{n}换成reflog里对应的编号
- 如果你还在变基的冲突解决流程中,直接执行:
执行带合并保留的交互式变基
运行命令:git rebase -i --rebase-merges master这时弹出的编辑界面会包含合并提交的指令,大概长这样:
pick A 特性分支第一个提交 pick B 提交B merge -C ME HEAD~1 master # 这是合并提交ME,-C ME表示保留原合并信息 pick C 提交C pick D 提交D修改提交列表实现压缩
把A、B、合并ME、C这些提交压缩成一个新提交C',修改后的列表如下:pick A 特性分支第一个提交 squash B 提交B merge -C ME HEAD~1 master squash C 提交C pick D 提交Dsquash表示把该提交的内容合并到上一个提交里merge -C ME会保留你之前合并ME时解决的冲突,不会让你重新处理
完成变基
保存退出编辑器,Git会自动处理压缩和合并,最终得到你想要的提交结构:D→C'→MA,而且合并时的冲突解决结果会被完整保留。
方案二:用merge --squash直接打包压缩提交
如果你不想处理合并结构的变基,也可以直接把需要压缩的提交内容打包成一个新提交,再把D移过来:
步骤:
回到原始特性分支
确保当前在你的特性分支,且指向提交D。基于master创建新分支
git checkout -b new-feature master打包A到C的所有提交内容
把特性分支上从A到C的所有内容(包括合并ME的冲突解决结果)打包到暂存区:git merge --squash your-feature-branch~1 # your-feature-branch~1就是提交C创建压缩后的提交C'
提交暂存区的内容,自定义提交信息:git commit -m "压缩提交C':包含原A、B、ME、C的所有内容"把D移到新分支上
用cherry-pick把提交D复制到新分支:git cherry-pick D替换原特性分支
切换回原特性分支,重置到新分支的状态:git checkout your-feature-branch git reset --hard new-feature最后可以删掉临时分支:
git branch -D new-feature
这样操作后,你也能得到目标提交结构,而且合并ME的冲突解决结果会被完整包含在C'里,不会丢失。
内容的提问来源于stack exchange,提问作者Minh Nghĩa

