什么Git分支模型适合你?

我们公司目前正在使用一个简单的中继/发布/修补程序分支模型,并希望build议哪些分支模型最适合您的公司或开发stream程。

  1. 工作stream程/分支模型

    下面是我所看到的这三个主要的描述,但是它们之间有部分矛盾,或者不足以解决我们遇到的后续问题(如下所述)。 因此,我们的团队迄今默认不是很好的解决scheme。 你做得更好吗?

    • gitworkflows(7)手册页
    • (nvie)一个成功的Git分支模型
    • (reinh)敏捷团队的Git工作stream程
  2. 合并与重新分配(纠结与顺序历史)

    是否应该pull --rebase等待回到主线,直到完成任务? 我个人倾向于合并,因为这保留了一个任务开始和完成的基地的视觉插图,我甚至更喜欢merge --no-ff为此目的。 但是它也有其他的缺点。 还有很多还没有意识到合并的有用性质 – 它是不可交换的 (将主题分支合并成主并不意味着将主合并到主题分支中)。

  3. 我正在寻找一个自然的工作stream程

    有时会发生错误,因为我们的程序没有用简单的规则来捕捉特定的情况。 例如,早期版本所需的修补程序当然应该基于下游,以便可以将上游合并到所有必要的分支(这些术语的用法是否足够清楚?)。 然而,在开发人员意识到它应该放置在更下游之前,一个修补程序会将其发送到主服务器,如果已经被推送(甚至更糟糕,合并或基于此),那么剩下的选项是樱桃采摘其相关的风险。 你用什么简单的规则? 此外,还包括一个主题分支的尴尬必然排除其他主题分支(假设它们从共同基线分支)。 开发人员不想完成一个function,开始另一个function,就像他们刚才写的代码不在那里一样

  4. 如何避免造成合并冲突(由于樱桃采摘)?

    合并冲突似乎是一种肯定的方式,就是在分支之间进行挑选,他们再也不能合并了。 在两个分支中应用相同的提交还原(如何做到这一点?)可能解决这种情况? 这是我不敢推动大部分基于合并的工作stream程的一个原因。

  5. 如何分解成局部分支?

    我们认识到,从主题分支组装完成的集成是非常棒的,但是我们的开发人员经常做的工作并没有明确的定义(有时候简单到“扯开”),如果某些代码已经进入了“其他”主题,根据上面的问题,它不能再被带出去吗? 你如何处理定义/批准/gradle/发布你的主题分支?

  6. 代码审查和gradle等适当的程序当然是可爱的。

    但是,我们根本无法把事情解决得足够清楚,有什么build议? 整合分支机构,插图?

以下是相关问题的列表:

  • 什么是一些好的策略,允许部署的应用程序是可修复的?
  • Git用于内部开发的工作stream程描述
  • 用于企业Linux内核开发的Git工作stream程
  • 你如何维护开发代码和生产代码? (感谢这个 PDF!)
  • git发布pipe理
  • Git Cherry-pick vs合并工作stream程
  • 如何挑选多个提交
  • 你如何合并select性文件与Git合并?
  • 如何樱桃select一系列的提交并合并到另一个分支
  • ReinH Git工作stream程
  • Git的工作stream程进行修改,你永远不会推回原点
  • 樱桃挑选合并
  • 正确的混合操作系统和私人代码的Git工作stream程?
  • 用Git维护项目
  • 为什么不能Git合并文件更改与修改父/母。
  • Git分支/重新组装好的做法
  • 什么时候“git pull –rebase”让我陷入困境?
  • 大型团队如何使用DVCS?

还要看看Plastic SCM在任务驱动的开发中写的是什么,如果不是你的select,请研究nvie的分支模型和他的支持脚本 。

DVCS开发人员最需要了解的最令人不安的function就是发布stream程 :

  • 你可以导入(取/拉)任何你需要的远程仓库
  • 你可以发布(推)任何(裸)回购你想要的

从这个angular度来说,您可以遵守一些规则来简化您的问题:

  • 只有在没有被推动的情况下重新分支分支(自上次分配以来没有推入)
  • 只能推到一个裸回购(从Git1.7起是强制性的)
  • 遵循Linus关于重组和合并的build议

现在:

工作stream程/分支模型

每个工作stream程都支持一个发布pipe理stream程 ,并针对每个项目进行量身定制。
我所能提到的工作stream程是:每个开发人员不应该创build一个function分支,而只需要一个“当前开发”分支,因为事实是:开发人员通常不知道他/她的分支会产生什么:function,几个(因为它结束了太复杂的function),没有(因为没有准备好及时发布),另一个function(因为原来的一个“变形”),…

只有“集成商”才能在“中央”回购站上build立官方特色分支,然后由开发者提取这些分支来重新合并他们适合该特征的部分工作。

合并VS rebasing(纠结vs顺序历史)

我喜欢我提到的答案(“ 内部开发git使用的工作stream描述 ”)

我正在寻找一个自然的工作stream程

对于修复,它可以帮助将每个修补程序与来自错误跟踪的故障单关联起来,这有助于开发人员记住在哪里(即在哪个分支,即“修复”的专用分支)他/她应该进行这样的修改。
然后,钩子可以帮助保护中央仓库免受未经validation的错误修复或从不应该推送的分支的推送。 (这里没有具体的解决scheme,所有这些都需要适应您的环境)

如何避免造成合并冲突(由于樱桃采摘)?

正如JakubNarębski在答复中所指出的那样,樱桃采摘应该保留在需要的地方。
如果你的设置涉及到很多樱桃采摘(即“这不是罕见的”),那么有些东西是closures的。

将恢复应用相同的提交(如何做到这一点?)

git revert应该照顾,但这并不理想。

如何分解成局部分支?

只要一个分支还没有到处推广,开发者就应该重新组织它的提交历史(一旦他/她终于看到开发的forms更加明确和稳定):

  • 如果需要的话可以有几个分支
  • 在一个分支内提交连贯的一组(参见修剪Git检查 )

正确的程序,如代码审查和gradle?

集成分支(在专门的集成)回购可以帮助开发者:

  • 在远程集成分支之上重新开发他/她的开发(pull –rebase)
  • 在当地解决
  • 把发展推向回购
  • 检查集成商,不会导致一团糟;)

我认为,我可能是错的,git最被误解的一件事是其分布式的性质。 这就使得颠覆你的工作方式变得非常不同,尽pipe你可以模仿SVN的行为。 这个问题几乎是任何工作stream程都会做的,这很好,但也有误导性。

如果我有我对内核开发的理解(我将专注于此),每个人都有自己的git仓库来开发内核。 有一个版本库,linux-2.6.git,由Torvalds负责,作为版本库。 如果他们希望开始针对“发布”分支开发function,那么人们会从这里克隆。

其他知识库做一些发展。 这个想法是从linux-2.6中克隆出来的,只要你喜欢,直到有一个新的function。 然后,当这个准备就绪的时候,你可以把它提供给一个被认为值得信赖的人,这个人将把这个分支从你的存储库中提取出来并合并到主stream中。 在linux内核中,这种情况发生在几个级别(可信赖的中尉),直到达到linux-2.6.git,此时它成为“内核”。

现在这里是令人困惑的地方。 分支名称根本不需要在存储库之间保持一致。 所以我可以把git pull origin master:vanilla-code并从我的仓库中的一个叫做vanilla-code的分支中获得一个来自origin的主分支。 提供我知道发生了什么事情,这并不重要 – 它是分布式的,所有的存储库都是对等的,而不仅仅是像SVN这样的多台计算机共享。

所以,考虑到这一切:

  1. 我认为这取决于每个程序员如何进行分支。 所有你需要的是一个pipe理发布等中央库。树干可能是head 。 发布可能是标签或分支,修补程序可能是分支本身。 事实上,我可能会以分支的forms发行,所以你可以继续补丁。
  2. 我会合并,而不是rebase。 例如,如果你拿一个仓库,克隆它,分支并做一些开发,然后从你的origin你应该在你的仓库,可能做另一个分支,并把最新的master合并到你的分支,以便其他人可以拉你的变化尽可能less的努力。 根据我的经验,很less有必要真正重新devise。
  3. 我认为这是理解Git工作方式的一个例子。 这需要一段时间和很多良好的沟通 – 我只有真正开始明白当我开始与其他开发人员使用git,甚至现在,有些事情我不知道。
  4. 合并冲突是有用的。 我知道,我知道,你想这一切工作,但事实是代码的变化,你需要将结果合并成有用的东西。 合并冲突实际上只是更多的编程。 我从来没有find一个简单的解释如何处理它们,所以这里是:注意到合并冲突的文件,去改变他们应该是, git add . 然后git commit
  5. 但它适合。 正如我所说的,每个用户的git存储库是他们自己的玩,分支名称不需要是相同的 。 例如,如果您有临时存储库,则可以强制使用命名模式,但不需要为每个开发人员使用,而只需要在发行版本库中使用。
  6. 这是合并阶段。 当您考虑代码审查/通过质量testing时,您只能合并到发布分支等。

我希望有帮助。 我意识到VonC只是发布了一个非常类似的解释…我不能打得够快!

编辑一些关于如何在商业环境中使用git的进一步想法,因为这似乎与评论中的OP有关:

  • 我们将其称为product.git的版本库可以由许多负责实际照顾产品本身的高级程序员/技术人员访问。 它们类似于维护者在OSS中的angular色。
  • 这些程序员也可能部分领导新版本的开发,所以他们也可能自己编写代码并维护varios存储库。 他们可能会pipe理登台存储库以获取真正的新function,他们也可能拥有自己的存储库。
  • 他们下面是负责开发个人位的程序员。 例如,有人可能会负责UI的工作。 他们因此pipe理UI.git存储库。
  • 在他们的下面是实际的程序员,他们将这些function开发为日常工作。

那么会发生什么? 那么,每个人从“上游”来源,即发布资源库(这也可能包含前几天开发的最新材料)开始,每个人都会拉。 每个人都直接这样做。 这将在他们的存储库中的分支,可能被称为“主”,或者如果你是我所谓的“最新”。 程序员然后会做一些工作。 这项工作可能是他们不确定的事情,所以他们做一个分支,做这个工作。 如果不起作用,他们可以删除分支并返回。 如果是这样,他们将不得不合并到他们目前正在工作的主要分支。 我们会说这是一个在latest-ui UI上工作的UI程序员,所以他做了git checkout latest-ui接着是git merge abc-ui-mywhizzynewfeature 。 然后他告诉他的技术主pipe(UI领导)嘿,我已经完成了这样的任务,从我身上拉下来。 所以用户界面的主angular不会git pull user-repo lastest-ui:lastest-ui-suchafeature-abc 。 然后,用户界面的领导在这个分支上看,实际上,这是非常好的,我会把它合并到ui-latest 。 然后,他可能会告诉下面的每个人,把他们ui-latest分支或他们给他们的任何名字从他身上拉下来,所以这个特征被开发者所探索。 如果团队很高兴,UI主pipe可能会要求testing主pipe从他那里撤出并合并这些更改。 这会传播给每个人(变化的下游),他们testing它并提交错误报告等等。最后,如果该function通过了testing等,那么最重要的技术线索之一可能会将其合并到当前的程序工作副本中,所有的变化然后传播回去。 等等。

这不是一种“传统”的工作方式,被devise为“同行”,而不是象SVN / CVS那样的“等级”。 实质上,每个人都有提交权限,但只能在本地访问。 它是对存储库的访问,以及将您指定为允许使用层次结构的发行版回放的存储库。

我用过的一个很好的结果如下:

一个“祝福”的回购,每个人都推动和拉出,基本上是一个客户端 – 服务器拓扑。

没有主分支,所以没有开发者可以将任何代码推入“主线”。

所有的进展发生在主题分支上。 我们使用命名空间名称来轻松检测由谁负责:jn / newFeature或jn / issue-1234

白板上的分支和看板/ Scrum卡之间也有近似1对1的映射。

要释放一个分支,它被推到祝福的回购和看板卡移动准备审查。

那么,如果分支机构被审查所接受,它就是一个发布的候选人。

当一组接受的分支合并在一起并用一个版本号标记时,就会发布一个版本。

通过将新标签推向有福的回购,新function有了新的基础。

为避免合并冲突,请恳求开发者更新(合并)未发布的分支到最新的发布标签。

就个人而言,我试着只保留主分支中的发布就绪代码。

当我在一个新的function或错误修复工作,我在一个分支。 我也在分支进行unit testing。 如果一切正常,只有这样我才能合并/重新融入主人。

我尝试使用通用的分支命名约定,例如:

  • 修正错误/ recursive_loop
  • 修正错误/ sql_timeout
  • function/ new_layout
  • function/ enhanced_search