如何在git合并中强制使用共同的祖先?

20
假设我有一个名为master的分支和一个名为upstream_lib的分支。分支master有一个子目录lib,它基于分支upstream_lib上的代码;定期使用子树合并策略将upstream_lib中的更改合并到master分支。master中的lib目录有一些自己的修改,这些修改在upstream_lib中不存在。
然而,假设两个分支没有共同的历史记录(例如,因为仓库刚刚迁移到Git),或者由于在upstream_lib中的合并被压缩,进行了一些重新基准定位或其他因素,导致合并基础不正确。
问题是:给定upstream_lib上的一组新更改,如何强制合并将其视为特定版本的upstream_lib的公共祖先?
1个回答

10
我从未使用过“子树(subtree)”策略,因此这可能是一个次优解(也可能不起作用^^),但您可以将upstream_lib中的所有新提交应用于master分支外的临时分支,然后进行合并。我考虑的方法没有从根本上解决您的情况,所以每次想要拉取新更改时都需要进行这种“手动合并”,但以下是其工作原理:
  1. 确定master祖先行中的虚拟公共祖先,比如master~100
  2. 确定upstream_lib行中的虚拟公共祖先,比如upstream_lib~150
  3. 制作upstream_lib分支的一次性副本:git branch --no-track new_upstream_lib upstream_lib
  4. 使用带有子树选项的递归策略将new_upstream_lib变基到master~100上。 (我认为您不能仅使用子树策略,因为正如您所说,master中的lib目录已经发生了变化。)以下是完全未经测试的命令:
  5. git rebase -s recursive -X subtree=lib --onto master~100 upstream_lib~150 new_upstream_lib
    

    注意,new_upstream_lib现在包含整个master树,尽管您只关心lib目录。

  6. 合并它:git checkout master && git merge new_upstream_lib && git branch -d new_upstream_lib

1
我想唯一的问题是与upstream_lib分支没有共享的历史记录或提交,但我可以接受这个。 - Artefacto
很高兴听到这个消息!如果您想强制共享祖先,可以创建一个初始的空提交,并将masterupstream_lib都变基到该提交上。当然,前提是upstream_lib是您自己的分支,而不是远程分支。但是,如果将upstream_lib最初导入lib目录的方式只是使用了cp而不是合并(如http://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html中所述),您仍然会遇到您描述的问题。 - Jo Liss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接