如何在不重新设置基准的情况下使 git 第一个 parent 一致?

How can one make git first parent consistent without rebasing?

我正在寻找一种方法来使用主题分支来创建功能开发的详细历史记录(以及正在进行的备份),并使用合并提交到 master 作为功能添加的摘要描述。好吧,在双向合并中使用 --no-ff,这就是你得到的,对吧。当您尝试推送并发现其他人已经将更改推送到 master 时,问题就出现了。

据我所知,此时您的选择是 (a) 重新设置您的本地 master 副本的基址 'over' 这些其他更改或 (b) 将这些更改合并到您的本地 master 副本中,然后推送.选项 (a),变基,有点乏味,并且以模糊事件顺序的方式重写历史。选项 (b),正常合并,导致历史图表模糊了主题分支与 'mainline' 的身份(特别是 git log --first-parent 不指代上游 master 的头)。

我想避免这两种结果,而且我认为只需要一个小的(可预测的)改变。我 认为 问题只是 git 将当前分支设置为合并的第一个 parent。合并两个本地分支机构时,这是有意义的。但是,将当前上游分支合并到本地时,这是落后的。那么怎么知道是上游分支呢?好吧,这就是跟踪分支的用途,对吧?您甚至可以使用名为 --set-upstream.

的选项来分配它们

所以...

  1. 在合并跟踪分支时交换 parent 的顺序会给出一个干净的历史记录,我错了吗?还是我遗漏了一些关于如何使用跟踪分支的信息?
  2. 如果它是当前本地分支的跟踪分支(以一种分发给克隆的方式),如何强制 git 使用源分支作为合并的第一个 parent回购)?

编辑

我最初针对这个问题的起始案例不是明确的主题分支,而是代表 semi-trivial 更改的单个提交仍然值得分享回 'mainline'。我希望该解决方案能够扩展到作为多个步骤(实际主题分支)开发的变更集,并且这种情况似乎更清楚地描述了意图,因此我将其用作描述。不幸的是,在 before 发现推送中的冲突会使事情复杂化(正如@Chris 迅速指出的那样)。

对于这个更简单的案例,我仍然对 (1) 和 (2) 的答案感兴趣(如果可以解决更简单的案例,我将编辑问题,并且我想出如何给予那些有已经回答了)。

您可以中止合并并使用新 master 重做。假设您在 master 上并且合并推送刚刚失败,您可以执行以下操作:

$ git reset --hard origin/master  # reset to newly-fetched master
$ git merge topic_branch          # redo the merge
$ git push origin HEAD            # re-push the merge

如果在初始合并中没有冲突,那没什么大不了的。否则你需要重做这项工作。为避免这种单调乏味,请参阅 git rerere.

针对您的具体问题:

  1. 是的,将初始合并(您的 master 版本未能推送)合并到新获取的 master 比从另一个方向合并更干净,但它仍然引入了无意义的合并。重做合并使历史更清晰。
  2. git merge 合并到当前分支,所以只需检查你想成为第一个父节点的内容。为避免推送被拒绝,请确保在合并之前从 master 拉取。