Git 如何使用源代码管理来管理同一项目的开源和商业版本?

Git 如何使用源代码管理来管理同一项目的开源和商业版本?,git,version-control,mercurial,repository,bitbucket,Git,Version Control,Mercurial,Repository,Bitbucket,我们正在开发一个开源项目,我们正在使用Mercurial进行源代码管理控制。该项目的Mercurial存储库是公共的(我们使用的是Bitbucket) 现在我们有了一个客户机,我们需要为其定制我们的开源软件。这些定制必须是私有的,所以我们可能需要为这个客户创建一个新的Hg存储库;这个新的存储库将是私有的 但问题是我们需要[不时]将开放存储库中的更改(如新功能或错误修复)合并到我们的私有存储库中 实现这一目标的最佳方式是什么?我读到有可能合并两个或多个Mercurial存储库,但历史记录将丢失。由

我们正在开发一个开源项目,我们正在使用Mercurial进行源代码管理控制。该项目的Mercurial存储库是公共的(我们使用的是Bitbucket)

现在我们有了一个客户机,我们需要为其定制我们的开源软件。这些定制必须是私有的,所以我们可能需要为这个客户创建一个新的Hg存储库;这个新的存储库将是私有的

但问题是我们需要[不时]将开放存储库中的更改(如新功能或错误修复)合并到我们的私有存储库中

实现这一目标的最佳方式是什么?我读到有可能合并两个或多个Mercurial存储库,但历史记录将丢失。由于许多冲突,合并也可能是痛苦的。如果我们在将来获得更多的客户端,我们应该如何管理它们的存储库呢?我们应该使用一个存储库和多个分支吗?如果这两个项目版本开始朝着不同的方向发展,而这两个存储库变得越来越不同,该怎么办

请分享你的经验


提前谢谢

原则上,基本模型相对简单;拥有一个单独的私有存储库,它是公共存储库的克隆(分支),在那里进行所有私有更改,然后定期将公共存储库合并到私有存储库中。在历史保存方面没有问题,我不知道你为什么读到会发生这种情况

然而,挑战是不要以无法维护的合并地狱结束,这只能通过严格的纪律来实现

任何长寿分支的最基本经验法则是:

  • 保持私人分支机构尽可能小。尽量减少代码中的更改量,并保持较小的更改量,这样就不会开始重构大量代码或更改缩进。在像这里这样的单向合并情况下,您修改的任何代码都有可能发生冲突,甚至是冲突

  • 经常合并。频率越高越好。如果您不这样做,那么每当您想要集成公共存储库中的更改时,您最终会遇到一个超级合并,它会产生大量冲突

  • 此外,在组织和编写代码以促进此场景时,您还应该遵守规则。对什么在哪个分支上的位置有明确的规则,并将代码分段

    理想情况下,您可以将定制功能建模为插件或外部库,甚至是单独的项目。这可能并不总是容易实现的,在这种情况下,至少尝试根据原始的子类编写所有私有修改,您可以使用工厂方法实例化这些子类。通过在仅存在于私有分支上的独立文件中进行所有更改,您可以将冲突风险降至最低

    还要编写自动测试。很多。否则,您将无法及时检测到合并问题(这将发生),并且私有分支经常会被破坏


    最后一个提示:在公共存储库上创建一个推钩子,拒绝任何包含您知道是私有的变更集的推送;这将防止私密代码的意外发布,并可能为您节省大量麻烦。

    您所描述的是分布式版本控制系统的标准功能:在两个存储库中开发,并将其中一个存储库保留为另一个存储库的子集。首先为私人开发制作克隆:

    hg clone open private
    
    然后进入
    private
    并在那里制作新功能。正常提交。
    private
    存储库现在将包含比
    open
    存储库更多的变更集,即新功能

    当修补程序和新功能作为正常开源过程的一部分放入
    open
    存储库时,您可以将它们拉入
    private
    存储库:

    cd private
    hg pull
    hg merge
    
    这样,您就可以保持不变:
    private
    存储库始终包含开放版本中的所有内容,以及私有增强功能。如果您正在处理私有版本,并且发现了一个bug,那么请记住查看开放版本,看看那里是否也存在bug。如果是这样,那么首先在开放版本中修复它,并将错误修复合并到私有版本中。如果您错误地修复了私有版本中的错误,那么使用
    hg transplant
    将错误修复复制到另一个开放版本

    历史不会有任何损失。当您执行
    hg merge
    时,您必须像正常情况一样解决合并问题,并且冲突只会与您的私有更改所需的冲突一样大

    要记住的重要一点是永远不要以另一种方式推动(或拉动),除非您想开始将一些私有更改发布到开源版本中


    您可以在不同的客户机上多次使用此设置,如果多个客户机需要相同的私有增强功能,您还可以根据需要在不同的私有存储库之间推/拉变更集。

    当然,还有一些扩展和变体

    • 对于Martin的工作流,您可以使用“每个任务的分支”范式(分支必须在基本项目中创建,“打开”)和“push-b--new Branch”(仅发布分支,而不是主线中的整个更改集)到“Private”,其中分支也必须合并为默认分支
    在这种情况下,增加的fork数量会使每个fork花费“+2个命令+1个存储库”

    • 分支的变化:单个开发人员的repo,许多命名分支(每个目标的分支+每个任务的分支)。第1节的小偏差-只有一份开发回购协议,其中包含开放式和私有命名分支机构(以及其他短期B分支机构)。任务也(如第1页)在单独的分支中实现,该分支(无推送)合并到所需的目标(开放和私有)。用户可见的开放式和私人回购协议也必须使用push-b更新
    增加的