如何在git中保持线性历史

3
出于不同的原因,我需要维护一个线性的主分支master。也就是说,在该分支中的提交不能有超过一个父提交。
我们团队中有多个人,我们想要创建feature分支一起工作。通常情况下,我们会将自己的个人提交变基到这个feature分支上,然后在功能准备好时将其合并到我们的devel分支上。我们还依赖于一个foreign项目(使用不同的分支,但在这里我们假设它都在一个单独的foreign分支中,并且有自己的独立来源),我们定期将其合并到我们的devel分支中。
然而,所有这些工作最终都必须以线性形式转发到master分支。我们可以将所有这些更改压缩成一个单独的提交master(使用git reset --soft devel),然后将master合并回devel。然而,我们希望尽可能地保留我们的提交:
  • 每个提交消息(包括合并消息)都应该被保留
  • 提交之间的拓扑顺序必须被保留
  • foreign分支合并的提交必须被压缩成一个单独的“合并”提交(不幸的是没有父信息)
  • masterdevelfeatureforeign分支必须保持完全向前兼容(因为这是一个共享库)
我的初始想法是:
  1. devel创建一个staging分支
  2. staging变基到master
  3. 将新的staging合并回devel中。
但这行不通,因为:
  • foreign分支是从其来源重新变基而不是压缩
  • 我必须再次处理来自devel的每个冲突,尽管它们已经在我们的许多合并过程中在devel本身中处理过了
所以我计划做以下事情:
假设divdevel中最新的未合并到master中的提交(最新的分歧点)。如果master有新的提交未合并到devel中,则放弃。也就是说,如果在div之后在master中有新的提交,则必须手动将其合并到devel中。
从 `div` 到 `devel` 的每个提交(按拓扑顺序),执行 `git reset --soft` 并将更改提交到 `master` 分支(使用相同的提交信息)。这意味着:
- 在 `div` 之后但在 `devel` 之前的提交被压缩:这些提交可能是从 `foreign` 合并过来的(如果是,则很好),或者是从 `master` 合并过来的(如果是,则实际提交已经在 `master` 中了)。 - 在中间的提交会一个接一个地正确推送到 `master`,除了与 `devel` 平行的分支,它看起来像在每次撤消另一侧的提交(这很丑,但可能无法避免)。
最后,将 `master` 合并回 `devel`,此合并提交成为下一次操作的 `div`。
由于我希望最小化“撤消”/“重做”的数量,因此我将以下限制添加到所选的拓扑顺序中:`devel` 中仅具有一个父级的提交将与 `master` 中的等效提交作为父级。
总的来说,这似乎过于复杂了。是否有内置的方法可以使线性分支跟随非线性分支?否则,我的策略是否有效,或者我漏掉了非常重要的细节?

2
考虑到 squash-commits 和 rebase 的风险性,使用特性分支似乎不是您团队的解决方案。您可能希望直接提交到主分支(虽然不如特性分支理想,但可以实现您所需的线性历史,并减少丢失提交的风险)。 - Makoto
1
我认为你不能同时维护主分支和开发分支并完成这个目标。你最好的选择似乎是放弃开发分支,从主分支中分离功能,然后在合并到主分支之前重新设置功能分支。如果你想在合并到主分支之前“组装”功能分支,你可以使用一个一次性的集成分支,并尝试利用rerere来避免在合并到主分支时不得不重新解决合并冲突的问题。 - jamey graham
foreign 分支怎么办?我无法变基它(它不在我的控制之下)。 - Nonyme
1个回答

1

正如@jamey's comment中所提到的,最好放弃develop分支,从master分支中拆分功能分支,并在合并到master之前进行变基。 当您完成一个特性分支时,可以执行以下操作:

git rebase master myfeature
git checkout master
git merge --ff-only myfeature

当您需要合并来自foreign分支的更改时,请执行以下操作:
git merge --squash foreign
git commit

来自git merge的手册页面:

--squash

生成工作树和索引状态,就好像发生了真正的合并(除了合并信息),但不会实际进行提交、移动HEAD或记录$GIT_DIR/MERGE_HEAD(以便下一个git commit命令创建合并提交)。这允许您在当前分支之上创建一个单独的提交,其效果与合并另一个分支相同(在章鱼合并的情况下可能是多个分支)。


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