我们团队已经热衷于采用rebase工作流,但我们可能有些过度,这就是这个问题的核心:你来评判。
现在使用pull --rebase对我来说已经是轻而易举的事情了。然而,我们还有大型的功能分支供多人共同开发。定期地,我们想要引入正在master分支上发生的更改。传统智慧会让我们合并,因为它是一个共享分支。然而,在我们迷恋rebase的过程中,我们决定对这些分支进行rebase。当然,这需要大家的配合。工作流程大概是这样的:
1)重新定位者与每个人协调,确保他们都在功能分支上检入并推送,然后要求他们在得到全部清除之前不再在该分支上进行任何工作。
2)重新定位者将功能分支rebase到master上,删除远程功能分支(git push origin: feature),然后推送新的、rebase过的功能分支(git push origin feature)
3)重新定位者让每个人获取最新状态,这将更新他们的功能分支,然后删除本地功能分支(git branch -D feature),创建一个新的本地功能分支来跟踪远程功能分支。然后每个人都可以得到全部清除。
这个工作流程有效,部分原因是我们是一个小组,工作中断很少。然而,我担心我们正在学习不良的Git习惯(在共享分支上进行rebase),或者这个工作流程将不能很好地扩展。
好处是,我们的代码库历史记录非常美妙。
Git大师们,你们认为我们是在玩火,还是采用了合理的工作流程?
更新:
自从我最初提出这个问题以来已经过去了两年,我们的工作流程已经发生了变化。我们仍然经常使用git pull --rebase
,所以这一点没有改变。这是常识,并且可以防止所有难看、混乱的小合并。 (我们保持基本同步,所以git pull --rebase
的代价很小)。
除此之外,偶尔英雄式地纠正错误,我们已经走出了变基的疯狂。 大多数情况下合并是有意义的。 然而,肆意合并是有问题的,并且确实导致了我两年前担心的混乱、混乱的历史。
我们的解决方案有几个组成部分:
主分支是"原始的"。 主题分支被合并进去后,一旦它们这样做,主题分支就被废弃了。 换句话说,将主题分支合并表示该工作已准备好投入生产,并且现在是主分支的一部分。 查看我们的版本历史记录,非常清楚正在发生什么:将主题分支合并到主分支中,就是这样。
必要时我们使用一次性集成分支。 例如,如果我们有主题分支A、B和C,它们都没有准备好集成到主分支中,但我们需要测试它们在一起,我们只需创建一个QA分支(通常是从主分支开始),然后将A、B和C合并在一起。 在某些时候,QA分支会被删除或重新使用。 关键是它不打算以任何方式永久存在,并且它没有与主分支相同的限制(您可以随时将主题分支合并几次)。 如果历史记录变得太混乱,您可以只删除QA分支并重新开始(这是我们发现非常自然的方法)。
在合并时,始终使用
git merge --no-ff
。 这是从两年前我们"线性提交历史"的痴迷中做出的如此巨大的逆转,值得一提。 现在我们已经放松了对线性提交历史的痴迷,并认识到合并是好的、有用的,我们已经开始依赖于主题分支是实际分支而不仅仅是最终与主分支合并的一系列提交。git merge --no-ff
确保总是有一个合并提交,即使没有必要。
我们对提交信息和分支有一个通用的约定,并且更重要的是,它与我们的问题跟踪系统进行了交叉引用。我们的问题跟踪系统使用数字问题编号,对于任何功能(或缺陷),我们都有一个问题编号(例如1234)。如果你正在处理这个问题,你将创建一个名为_1234
的分支,并在每个提交信息的开头使用"_1234: doing blah blah"
。这可能看起来有点过于琐碎,但它确实为我们工作得很好,显著地减少/消除了混乱。
使用git封装器来鼓励工作流程的吻合。这是我们目前正在努力的事情,但我们意识到这完全是必要的,以防止简单易懂的错误,例如从错误的地方创建分支(最近我们在一次灾难中,开发人员从一次性QA分支创建了一个主题分支:该主题分支已被批准上线,它被合并了...而不是被批准上线的一堆变更也进入了项目中)。我们的git封装器将要求确认,每当您做一些不寻常的事情(例如创建一个不是基于master的分支,创建一个名称不是_NNNN的分支,提交信息不以_NNNN开头等)。偶尔,我们确实需要做这些事情,因此封装器并不会阻止它,但它确实可以防止人们意外地做一些不该做的事情。
git pull --rebase
,并通过rebase来纠正工作流问题,但大多数情况下我们会合并分支。 - Ethan Brown