哪些Git分支模型适合您?


378

我们公司目前正在使用简单的主干/发行版/修补程序分支模型,并希望就哪种分支模型最适合您的公司或开发过程提出建议。

  1. 工作流程/分支模型

    以下是我所见过的三个主要描述,但它们在某种程度上相互矛盾,或者不足以解决我们遇到的后续问题(如下所述)。因此,到目前为止我们的团队默认的解决方案不是那么好。你做得更好吗?

  2. 合并与重新计算(纠结与顺序历史记录)

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

  3. 我正在寻找自然的工作流程

    有时会发生错误,因为我们的过程无法使用简单的规则捕获特定的情况。例如,早期版本所需的修复程序当然应该基于足够的下游,以便可以将上游合并到所有必要的分支中(这些术语的用法是否足够清楚?)。但是,碰巧的是,在开发人员意识到应该将修补程序放置在更下游之前,将修补程序放入了母版中,如果该修补程序已经被推送(甚至更糟,已合并或基于此内容),那么剩下的选择就是挑剔的选择,其相关的危险。您使用什么样的简单规则?这也包括一个主题分支的尴尬,它必然排除其他主题分支(假设它们是从同一基准分支出来的)。开发人员不想完成一项功能就可以开始另一种功能,就像他们刚刚编写的代码不再存在一样

  4. 如何避免造成合并冲突(由于选择问题)?

    建立合并冲突的肯定方法是在分支之间进行选择,它们再也无法合并了吗?是否可以在任一分支的还原中应用相同的提交(如何执行此操作?)可能会解决这种情况?这是我不敢推动基于合并的工作流的原因之一。

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

    我们意识到,从主题分支组装完成的集成会很棒,但是我们开发人员的工作通常没有明确定义(有时像“四处寻找”一样简单),并且如果某些代码已经进入“杂项”主题,根据上面的问题,它不能再次带出那里吗?您如何定义/批准/毕业/发布主题分支?

  6. 适当的程序,例如代码检查和毕业,当然会很可爱。

    但是我们根本无法解决问题,有任何建议吗?整合分支,插图?

以下是相关问题的列表:

还请查看Plastic SCM在任务驱动开发方面写的内容,如果您不是选择Plastic,请研究nvie的分支模型及其支持脚本


2
哈哈,谢谢,的确如此……我实际上已经阅读了其中的大部分内容:-)。这是我众所周知的-不是为了平庸的解决方案而定,而是继续寻找完美的解决方案。通常这是一个错误,但是在这种情况下,很多事情都将危在旦夕,而手头的解决方案太凌乱或太差,我需要继续寻找。因此,我决定列出所有与此有关的问题。
HiQ CJ

塑料SCM博客把自己的意见加入讨论,它至少有见地:codicesoftware.blogspot.com/2010/08/...
HiQ的CJ

1
使用“ merge --no-ff”时必须小心,请注意以下事项sandofsky.com/blog/git-workflow.html
Doppelganger

1
@Doppelganger我想对--no-ff应该如何引起您发布的链接中所述的问题感兴趣。对我来说,所描述的问题是带有检查点提交的bisect失败,而git blame未能在这种情况下提供帮助-但我看不到“ --no-ff”如何更改任何内容,而不是不使用它。作者抱怨说,与--no-ff的合并不会使文件被修改-但是没有它,文件也不会被修改,您还只会在历史记录中看到较旧的提交,对吗?
编码2014年

其他分支模型:仙人掌模型 barro.github.io/2016/02/…主线模型 bitsnbites.eu/a-stable-mainline-branching-model-for-git。这两个分支模型提供了不同于gitflow的另一种方法。
Mathieu Momal

Answers:


90

DVCS的新开发人员需要实现的最令人困扰的功能是发布过程

  • 您可以导入(获取/拉取)所需的任何远程仓库
  • 您可以发布(推送)到您想要的任何(裸)存储库

由此,您可以遵循一些规则来简化您的问题:

  • 仅在尚未推送分支的情况下才对其进行重定位(自上次重定位以来未推送)
  • 仅推送至裸仓库(自Git1.7起强制执行)
  • 遵循Linus关于重组和合并的建议

现在:

工作流程/分支模型

每个工作流程都在其中以支持发布管理流程,并且该流程是针对每个项目量身定制的。
我可以添加到您提到的工作流程中的是:每个开发人员都不应创建功能分支,而只能创建“当前开发”分支,因为事实是:开发人员通常不知道他/她的分支将确切产生什么:一个一个功能,几个(因为它最终会使功能太复杂),一个(因为未及时发布),另一个功能(因为原始功能已“变形”),...

只有“集成商”才能在“中央”存储库上建立官方功能分支,然后开发人员可以获取这些分支,以重新整理/合并适合该功能的部分工作。

合并与重新设置(纠结与顺序历史记录)

我喜欢您提到的答案(“ 内部开发中git使用的工作流说明 ”)

我正在寻找自然的工作流程

对于修订,它可以帮助将每个修订与错误跟踪中的票证相关联,从而帮助开发人员记住他/她应在何处(即,在哪个分支上,即“修订的专用分支”)进行此类修改。
然后,钩子可以帮助保护中央存储库免受未验证的错误修复程序或不应推送的分支的攻击。(这里没有特定的解决方案,所有这些都需要适应您的环境)

如何避免造成合并冲突(由于选择问题)?

正如雅库布·纳伦斯基(JakubNarębski)回答中所说的那样,应将采摘樱桃留给需要的罕见情况。
如果您的设置涉及大量的摘樱桃(即“这并不罕见”),那么情况就不对了。

将在还原中应用相同的提交(如何执行此操作?)

git revert 应该注意这一点,但这并不理想。

如何分解成局部分支?

只要尚未将分支推向任何地方,开发人员就应该重新组织其提交的历史记录(一旦他/她最终看到开发的形状更加确定和稳定),就可以:

  • 如果需要,几个分支(一个通过明确标识的功能)
  • 一个分支内的一组一致的提交(请参阅Triming Git Checkins

正确的程序,例如代码审查和毕业?

集成分支(在专用集成中)存储库可以帮助开发人员:

  • 在该远程集成分支的基础上重新建立他/她的开发(拉--rebase)
  • 本地解决
  • 将开发推向该仓库
  • 与不会导致混乱的积分器核对;)

@UncleCJ:正如您所看到的,这并不是您“最终问题” 的最终答案;)
VonC 2010年

我了解,我也有很好的讽刺意味,没关系;-)
HiQ CJ 2010年

3
@UncleCJ上游是您定期从我的帖子中撤出的所有提交都结束的地方(以SVN的说法是发行版本或主干)。下游是他们下面的每个人。向上游发送东西是将其合并到版本库(如linux-2.6)中的过程,而向下游发送则是从那里进行的更改,或者是从您的存储库中进行的更改,例如向您的奴才开发这种功能的经理。卑鄙的团队。

2
@UncleCJ:“我仍然很难调整您的签入范围以实现严格的顺序历史记录”:使用Git1.7 rebase --interactive --autosquash会更容易,它会自动以另一个提交消息的相同开头自动移动所有提交。如果这些提交使用票证编号(例如),即使当时未按顺序进行与该票证相关的那些修复,则自动压榨可以对这些提交进行快速重新排序。
VonC

1
@UncleCJ:“严格顺序的历史记录(是否有必要?!)”:并非总是必要的,但是它有助于跟踪功能依赖关系stackoverflow.com/questions/881092/…)和语义冲突stackoverflow.com/questions) / 2514502 /…
VonC

21

我认为而且我可能错了,关于git的最误解之一就是它的分布式特性。尽管您可以根据需要模仿SVN行为,但这使您在工作方式上说颠覆非常不同。问题几乎是任何工作流程都可以做到的,这很棒,但也容易引起误解。

如果我对内核开发有所了解(我将重点介绍),那么每个人都有自己的git存储库来开发内核。有一个存储库linux-2.6.git由Torvalds负责,它充当发行存储库。如果人们希望开始针对“发行”分支开发功能,则可以从此处克隆。

其他存储库做了一些开发。这个想法是从linux-2.6进行克隆,并根据需要进行多次分支,直到拥有有效的“新”功能为止。然后,当准备就绪时,您可以将其提供给被认为受信任的人员,该人员将把此分支从您的存储库中拉到他们的分支中,并将其合并到主流中。在linux内核中,这会在多个级别(受信任的副官)上发生,直到达到linux-2.6.git为止,在该点上它成为“内核”。

现在,这里变得令人困惑。分支名称完全不需要在存储库之间保持一致。因此,我可以git pull origin master:vanilla-codeorigin存储库中名为的分支的master分支中获取一个分支vanilla-code。只要我知道发生了什么,就没关系了-它的分布是所有存储库都是彼此对等的,而不仅仅是在SVN等多台计算机之间共享。

因此,请牢记所有这些:

  1. 我认为,这取决于每个程序员如何进行分支。您只需要一个用于管理版本等的中央存储库即可head。发行版可能是标签或分支,而修补程序本身可能就是分支。实际上,我可能会将发行版作为分支,以便您可以继续对其进行修补。
  2. 我会合并,而不是变基。例如,如果您使用一个存储库,对其进行克隆,分支并进行一些开发,然后从您origin的存储库中拉出,则应该在另一个存储库中进行分支,然后将最新的合并master到其中,yourbranch以便其他人可以花很少的精力就可以进行更改。可能。根据我的经验,很少需要真正地重新定基。
  3. 我认为这是了解Git的工作方式以及它可以做什么的一种情况。这确实需要一段时间并且需要很多良好的沟通-当我开始与其他开发人员一起使用git时,甚至直到现在,我才真正开始了解发生了什么事情,即使现在,我仍然不确定某些事情。
  4. 合并冲突很有用。我知道,我知道,您希望所有这些工作正常,但是事实是代码更改,您确实需要将结果合并为有效的内容。合并冲突实际上只是更多的编程。我从来没有发现适合做什么关于他们一个简单的解释,所以在这里它是:注意,有合并冲突,去改变他们,他们应该是什么,该文件git add .,然后git commit
  5. 但是它适合。就像我说过的,每个用户的git存储库都是他们自己的,可以使用,分支名称不必相同。例如,如果您拥有一个临时存储库,则可以强制执行命名架构,但是不需要为每个开发人员都需要,只需在发行版本库中即可。
  6. 这是合并阶段。仅当您考虑对代码进行审核/通过质量测试时,才合并到发行分支等中。

希望对您有所帮助。我意识到VonC刚刚发布了一个非常类似的解释……我输入的速度不够快!

编辑有关如何在商业环境中使用git的更多想法,因为这与注释中的OP相关:

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

那会怎样呢?好吧,每个人每天都从“上游”源(即发布存储库)中拉取信息(该源也可能包含前几天开发的最新资料)。每个人都直接这样做。这将在其存储库中的一个分支上进行,可能称为“ master”,或者如果您是我,则称为“ latest”。然后,程序员将做一些工作。这项工作可能是他们不确定的事情,因此他们创建了一个分支,进行了这项工作。如果不起作用,他们可以删除分支并返回。如果是这样,他们将必须合并到当前正在处理的主分支中。我们会说这是一个UI程序员工作latest-ui所以他git checkout latest-ui接着git merge abc-ui-mywhizzynewfeature。然后,他告诉他的技术负责人(UI负责人),嘿,我已经完成了这样的任务,请从我这里拉开。因此,UI主管确实如此git pull user-repo lastest-ui:lastest-ui-suchafeature-abc。然后,UI主管在该分支上对其进行查看,并说,实际上,这很好,我将其合并到中ui-latest。然后,他可能会告诉他下面的每个人从他们的ui-latest分支机构或他们给他们命名的任何名称上退出他,因此开发人员会探索该功能。如果团队满意,UI负责人可能会要求测试负责人从他那里撤下来并合并更改。这会传播到测试它并提交错误报告等的每个人(更改的下游)。最后,如果该功能通过了测试等,则顶级技术负责人之一可能会将其合并到程序的当前工作副本中。然后将所有更改向下传播。等等。

它不是一种“传统”的工作方式,而是被设计为“对等驱动”,而不是像SVN / CVS这样的“分层”。本质上,每个人都具有提交访问权限,但只能在本地。可以访问存储库以及您将哪个存储库指定为版本库,从而允许您使用层次结构。


非常感谢您的广泛回答(和投票),我将再花一些时间阅读其中的有用信息。但是,我们是一家公司,而不是OSS开发委员会;-),我必须向开发人员提供更清晰的指导,而不是“在您自己的存储库中随意摆弄”。让我们看看这篇文章的去向,我感到势头不错,请继续前进!
HiQ CJ

@VonC谢谢。@UncleCJ是的,但是我敢肯定,您有发布管理器等。有权访问存储库的任何人都可以执行这些操作。至于开发,为什么不给开发人员在合理范围内进行分支的自由呢?只要您有一些同意合并的协议,并且您可以根据自己的喜好命名中央存储库,就没有问题了。话虽这么说,一个通用的命名架构并不是一个坏主意。我倾向于将Initials-version-feature-subbranches用于个人分支,将version用于分支。

@UncleCJ我添加了一个示例说明它如何在公司中工作。从本质上讲,它是由经理代替的OSS角色,但是您明白了。与SVN相比,它还有一个额外的好处,即您的开发人员也可以脱机工作(他们只需要拉动网络),并且我认为,如果实现得当,可以更轻松地测试功能。

哇,这实际上是一个很好的例子,我们可能会在毕业时开始使用类似的东西。我并不是很想说,因为我们不做OSS,所以每个人都必须受到监管,所以我们实际上是一个很小而扁平的团队,但是我们必须努力在紧凑的时间表上进行有效的协作,并且还必须学习团队合作。这就是为什么我在这里问这些愚蠢的问题,以便稍后为团队的其他成员提供帮助:-)。我还从#git中意识到,基线定义不清,加上缩短交货时间的压力,这使我们无法自拔……稍后再回来。
HiQ CJ

这很公平-我最近去过那儿,正是通过尝试它并失败了很多,然后再适应一些OSS项目的工作方式,我才拿到这个例子。我想真正的大问题是,无论您如何分支以及您的存储库在哪里...您都可以按自己想要的任何方式定义它们,这无论如何对我来说都是一个震惊!但是它允许您做一些有趣的事情。无论如何,祝你好运,玩得开心!

9

我使用的效果良好的模型如下:

每个人都有一个“有福”的回购,基本上是一个客户端-服务器拓扑。

没有master分支,因此没有开发人员可以将任何代码推送到“ mainline”中。

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

白板上的分支机构和看板/ scrum卡之间也存在接近1对1的映射。

要释放分支,将其推送到有福的回购协议,然后将看板卡移至准备进行审查的位置。

然后,如果分支被审核接受,则它是发布的候选者。

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

通过将新标签推入有福的仓库,新功能就有了新的可能基础。

为避免合并冲突,恳请开发人员将其未发布的分支更新(合并)为最新的发布标签。


2

就个人而言,我尝试在master分支中仅保留可发布的代码。

当我使用新功能或错误修正时,我会在分支中执行此操作。我也在分支机构进行单元测试。如果一切正常,那么只有我才能合并/重新设置为主节点。

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

  • 错误修正/递归循环
  • 错误修正/ sql_timeout
  • 功能/新布局
  • 功能/增强搜索
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.