如何从当前HEAD向可达历史提交创建True merge且不修改工作树?
需求背景
假设最近4个提交对应一项功能变更,我希望通过--no-ff合并将其合并至初始状态——既保留单个提交的变更原因说明,又让合并提交信息阐述功能内容及用户收益。
第一次尝试
我可以重置分支,再用--no-ff合并之前的HEAD:
git reset HEAD~4 --hard # 将HEAD重置到功能开发前的提交 git merge --no-ff HEAD@{1} # HEAD@{1}是之前的HEAD,即我的功能提交集合
该操作能生成符合要求的提交,但git reset --hard会修改工作树,尽管最终状态与初始状态一致。修改工作树可能引发不良后果,例如TypeScript/JavaScript语言服务tsserver可能出现100% CPU占用,还可能触发自动测试带来非预期副作用。
不修改工作树的尝试
因此我希望在不修改工作目录的前提下完成该操作。查阅merge文档后,我了解到需要创建True merge,即从MERGE_HEAD合并至HEAD。仅设置MERGE_HEAD并不足够,于是我尝试模拟git merge --no-ff执行过程中的后台操作:
# 重置到目标合并基准,但保留工作目录 git reset HEAD~4 git update-ref MERGE_HEAD HEAD@{1} # 从merge文档中查到的操作 git update-ref ORIG_HEAD HEAD # 文档里没写,但`merge --no-ff`会更新这个引用 echo "no-ff" > .git/MERGE_MODE # 文档里没写,但`merge --no-ff`会创建这个文件 git add . # 从merge文档中查到的操作 git merge --continue
虽然生成了提交,但该提交仅包含一个父节点,而非两个。我还注意到--no-ff会生成指向提交根树对象的AUTO_MERGE文件,于是尝试添加该文件(测试中硬编码树对象ID,因不知如何从提交获取根树ID):
git update-ref AUTO_MERGE f9e3c4cb... # 仅用于本次测试
但这并未产生效果,新提交仍只有一个父节点。
问题
- 如何手动创建包含两个父节点的提交?
git merge --no-ff <ref>执行过程中存在哪些我未发现的后台逻辑?
说明
已采纳的答案恰好解决了第一个问题,即手动创建双父提交的优雅方案,但我仍对merge --no-ff中的隐藏逻辑感到困惑。
内容的提问来源于stack exchange,提问作者Pete
相关产品推荐
相关产品推荐

