首页 > 解决方案 > 如何使用 git 展平两个顶级合并提交

问题描述

我最近遇到了一个我不知道如何处理的 git 场景。首先让我们设置场景。

理想的工作流程

假设您正在维护一个大型开源项目的分支,上游正在使用拉取请求 (PR) 进行开发。由于上游正在做 PR,他们的 git 历史有很多合并提交。

您必须定期将您的树与上游同步。通常情况是这样的:

此时,您在树的顶部有一个整洁的小合并提交。嵌套在里面的是上游的所有提交和合并。你运行你的持续集成测试 (CI),它们通过并且分支被合并到你的 fork 的主分支中。精彩的。

有问题的场景

此时,您的sync分支包含您编写的两个合并提交。每个单独的合并提交都包含上游的各种提交和合并。

您现在可以运行 CI 并合并,但您不应该这样做,因为您的第一次合并提交会干扰 future git bisects。理想情况下,您将有一个合并提交,它是两个按顺序合并提交的总和。

如何将这两个合并提交合并为一个,但保留上游的 git 历史记录?

笔记

git rebase --preserve-merges是a)已弃用,和b)全部或全部。您不能有选择地保留所有上游的合并,而是展平您的合并。

我尝试使用git rebase --rebase-merges -i origin/master并标记第二个合并f以进行修复,但这并没有达到预期的效果。我对从未接触过的文件进行了合并提交。

一种解决方案是在上游已修复后从头开始重做整个合并。问题是,即使rerere这样也会有很多工作。在这些上游同步中,您最终会修复不是合并冲突的东西,而是(例如)编译或逻辑错误。因为这些修复是合并冲突(单独提交)的次要修复,rerere所以不会为它们记录自动解决方案。

标签: gitgit-rebase

解决方案


如果我理解正确,您需要一个合并提交:上游树,包括最近的修复,与您的sync分支合并。所以,这就是您应该做的:将您的同步分支重置为原始合并之前的提交,然后再次执行合并。

如果您在原始合并之后但在上游修复可用之前对同步分支进行了其他更改,您可以先将这些提交重新设置为原始合并之前的提交:

git checkout -b sync
git rebase --onto ${PREMERGECOMMIT} ${MERGECOMMIT}
git pull upstream master

推荐阅读