《配置管理最佳实践》——1.3 源代码管理核心概念

1.3 源代码管理核心概念

就像其他学科一样,源代码管理也有它自己的术语。可能你以前从其他一些配置管理人员那里听到一些技术行话却百思不得其解,读过这一章你就不会再对这些术语感到陌生了。这一章将会帮助你理解这些核心概念。理解了这些概念对理解源代码管理最佳实践也是非常有帮助的。

1.3.1 建立基线和时间机器
许多开发者认为源代码管理就是简单地从源代码管理工具中(一个代码库)签入和签出代码。就像大多数人认为的那样,多年前一些比较老的版本管理系统的确是这个样子。如今,虽然大多数配置管理代码库具备的可靠性和功能性不同,但都能支持变更,确保所有变更的安全。简单地签入代码到源代码管理工具中确实是必需的,但是在配置管理过程中这显然是不够的。实施有效的源代码管理,要点是提供一个虚拟的时间机器,可以随时把你带到一个特定的时间点,通常是一个稳定版本发布时代码的某个状态。对于某个特定发布,识别出其源代码的确切版本,常常称作建立代码基线。一些权威的资料中称此为代码的配置。对于用这个特定的术语,我认为它有误导性。在第3章“环境配置”中,我们将会讨论配置这个词更好的用法。

很多配置管理工具把建立基线的操作叫作给代码做标记(tagging)或标签(labeling)。也有的工具在涉及相互依赖的多个组件时用代码快照(Snapshotting) 这个术语。基线是不可改变的。这就意味着你必须具备可以锁住标记或者标签使其无法修改的能力。这一点是非常重要的,因为我们必须有一个代码版本不变的记录,从而构建出部署到生产环境(或QA环境)中的发布。除了标记(或标签)用于创建基线,很多人用额外的标记(通常称作“生产”)来指出生产环境中的当前版本,或者指那些最后完好的构建。标记是可以随着生产环境中代码的当前基线浮动的。生产环境下的代码发生变化了,对应的标记也要变化。这是一种常见而且方便的做法。但是这种做法是不能用来替代创建基线的,因为它不能用来识别那些已经被发布到生产环境(或QA环境)下的代码。区别就在于基线是不能改变的,而标记是可以改变的。大多数优秀的源代码管理工具对标记或标签用元数据来实现。元数据是关于数据的数据。这意味着源代码管理存储库中保留着一个单独数据库,用来记录签入代码库中代码的信息。元数据包括签入的注释,相应缺陷(触发对代码的变更)的链接,以及记录了代码合并的链接。事实上,所有针对代码的变更都应该用变更请求(CR,Change Request)来跟踪,这样你就可以确切地知道为什么会进行某个变更。很多源代码管理工具利用元数据提供了一系列丰富的特性,如在很多年后依然可以为用户提供从代码库创建后的所有变更历史。在处理跟踪变更时,通常的做法是在开发前期采用一个轻量级(非正式化)的过程,然后随着软件即将发布变得越来越严格,并且要一直保持这种趋势。这是一个很好的把敏捷和精益原则应用到配置管理的例子。在第9章“合理精简过程”中我们将会讨论这些。一些源代码管理工具用分支创建基线,这也许不是最优的办法,因为分支上的代码常常是可以修改的,除非利用一些机制来锁住分支。利用分支来创建代码基线的工具之所以这样做是因为工具性能上的局限。在这类工具中创建分支要比创建标记或标签快。虽然一些配置管理工具的确尝试用分支来创建基线,但是这并不是分支的常见用法。我们将会在这章的后面部分对此进行讨论。首先,我们需要了解源代码管理中的签入和签出。

1.3.2 保留与非保留签出
保留与非保留签出,也就是我们经常说的代码是否可以锁住的问题。一些源代码管理解决方案是建立在保留签出模型1基础上的。默认情况下,当一个开发人员想做修改而签出一个文件时,存储库就会在这个文件的版本上放置一个锁。其他源代码管理工具是基于非保留签出模型工作的(有时也被称为“乐观签出模型”)。这就意味着不管有多少个开发人员同时签出并且修改代码,存储库都不会在该文件上放置锁。我比较倾向于使用保留签出模型,因为这可以主动地让我知道我是否正在尝试和别人修改同一个文件。乐观签出模型可能会造成额外的合并代码的工作,如果开发人员知道他们在试图同时修改相同的文件,这种形式的合并本来是可以避免的。当其他人试图和你修改同一段代码时,一些现代的源代码管理工具会通过提高可视化的方法来避免这种问题。另外一个非保留签出的用途是简单地得到一份可写的(可能永远不会签回到存储库的)文件副本。

1.3.3 沙箱和工作空间
大多数源代码管理工具都有私有沙箱和工作空间的概念。在私有沙箱里,你可以隔离你的工作,然后签入你的变更,如果有必要,还可以合并更改到另外一个分支(通常被称作代码集成)。普遍的做法是开发人员有多个工作空间(或沙箱)来协调和安排自己的工作。分支提供了一个安排工作的有效方法,并且提高了开发人员的生产率。

我的第一个沙箱

当我介绍配置管理和如何使用源代码管理工具的时候,我常常提到小时候在沙箱里玩的经历。像很多其他男孩一样,我喜欢牛仔、军队士兵和其他玩具娃娃。我家隔壁是一个小女孩,她时常到访,在我的沙箱里玩她的玩具娃娃。不可避免地,我在玩牛仔的时候扔得到处是沙子,然后苏西就跑回家抱怨我把沙子弄到她的娃娃上了。结果你也知道了,给我带来了很大的麻烦。之所以提到这件事情,就是想说明不应该让别人进入你的私人沙箱,否则你就会遇到麻烦。在隔离并且受控的环境中工作是软件开发中提高生产率的首选方法。良好定义的处理代码变体的方法是提高生产率的另外一个方面。
1.3.4 变体管理(分支)
变体(variant)是指同一产品不同版本之间具有很多相同功能,但是又有区别的情况。优秀的源代码管理工具最重要的特性之一就是很容易地支持相同代码库的多个变体。这样就可以很容易地支持在相同代码库下仅为了某些特殊需求而对代码子集的修改。创建变体常常是创建多条并行的开发线来实现,通常被称作分支。创建分支的原因有很多。例如,想写某个软件显示一个国际时钟。这个时钟最基本的功能都是一样的,无论此时钟是运行在Windows, Mac, Linux 或者是 Unix 的机器上。但是,为了使这个时钟可以工作,需要一个函数去读底层的操作系统时钟。因此,编码了一个特定模块来处理那些为每个操作系统定制化的系统调用。

在实践中,我们假设Linux 上通用的共同代码将放在主分支(main branch)[通常被称为主干(trunk),主(main)]。然后我们创建了一个变体(例如,Windows, Mac, 和 Unix分支),这些变体都包含了主干上的所有代码和另外一些必需的修改(例如,针对特定系统时钟的操作系统调用)。在这个例子中(如图1.1所示),所有分支唯一不同的代码是系统时钟查找函数。通过这种方法,可以有效地管理代码的不同变体。

图1.1 程序hello.c最初是在Linux下编写的,然后在特定的操作系统分支上进行了修改。相对Linux 上的版本,每一个都叫作一个代码的变体。

1.3.5 复制分支与增量分支
一些源代码管理工具要求所有的分支是主干上所有代码的一个复本。如图1.2所示,这种做法通常叫作拷贝分支。其他工具则是仅仅包含发生改变的代码(通常叫作增量分支)。

主干是分支的基础。有时分支会很复杂,尤其是当人们开始用分支管理所有的开发活动时。一个常见的做法是每修复一个缺陷就建立一个分支。这种做法常被称作建立功能分支。

图1.2 拷贝分支是组织代码变体一个通常的做法。

1.3.6 如何处理缺陷修复
支持缺陷修复通常是一个最常见的创建分支的需求。例如,你正在写“Hello world”程序时,想在屏幕上也显示一个漂亮的时钟。这是一个现在版本不需要的额外功能。在将程序发给客户几天后,你发现每个月第三个星期二的时间都是错误的。图1.3 展示了这种情况。虽然时钟不是这个发布版本的内容,但是我们不能容忍屏幕上的时钟是错误的。

图1.3 在版本3中,已经开始的工作也许几个月也完不成,但是现在该如何修补时钟出现的问题呢?

程序的其他部分工作得都很好,所以只要把时钟隐藏起来,让客户看不到错误的时间就可以了。在产品的下一个版本中,我们会发布一个带有全新时钟的控制台,这个问题就不会存在了;而目前我们需要为客户提供一个快速的修复,把这个错误的时钟给隐藏起来。现在的问题是我们已经在版本3上做了很多只有在下个版本中才会发布的更改,可那已经是2个月后的事情了。而与此同时,我们需要发布一个临时解决代码问题的缺陷修复,如图1.4所示。

图1.4 版本2.1的缺陷修复提供了一个可以立刻解决问题的补丁(隐藏那个错误时钟)。

1.3.7 流
流是另外一种强大的管理代码变体的方法。虽然和分支十分类似,但是流常常具有强大的管理代码变体的特性。如下是其中的一些特性:

  • 清楚的使用范例
  • 清楚直观的层次组织结构
  • 流之间管理和操作变更集的能力(有时须借助工作空间)
  • 通过快照建立代码基线的能力
  • 找到并获取组件的某一个特定基线的能力
  • 找到并获得特定快照的能力(例如一个或者多个组件的基线)
  • 强大的安全授权和认证机制
  • 有助于流设计和使用的可视化流拓扑结构图
  • 可提供追溯能力的完整历史信息

例如,一些源代码管理工具可以层次化地组织流。也就是说,有一个父级流(常被用作集成)和子级开发流。一些源代码管理工具可以允许你动态地变更子流的源。这个特性很有用,可以让你在接口还未完成的组件上十分方便地工作。例如,创建一个代码桩(Code stubs or mocks), 把其放在一个临时流中供使用,一旦那些代码被真正实现后再变更流的源。变更从子流到其父流的提升,也被称为交付(deliver)。通常的做法是在交付特定变更集(Changesets)到上一级父流的时候,子流首先要从父流更新 (有时也称作变基,rebasing) 中得到最新的更改。最佳实践的做法是变基代码到私有的工作空间,进行测试确保成功构建,然后交付变更到父级流。流通常有流向这个概念,以便变更集可以从一个流复制(或者说提升)到另外一个流。当有开发流和集成流的时候,通常会选择这么做。发布管理团队(RM, Release Management)通常有一个自己控制的单独分支来确保可以独立地构建、打包、发布代码和部署(常常由运维团队来做)。没有流,就需要额外的工作来将源代码管理工具和缺陷或变更跟踪系统集成到一起来组织分支,特别是如果想让每个分支仅实现一个功能。在实际中,流比分支提供了更多的功能。流有点复杂,但是更强大,因此值得去学习和理解它们的用法。
1.3.8 合并
分支是一个很强大的特性,许多开发员发现分支可以帮助他们更有效地工作。问题是我发现很多开发人员忘记拉出分支的代码需要经常合并(Merging) 回主干。例如,在一个分支上修复了一个bug,通常在主干上也需要修复(假设这两者之间是相关的)。从分支合并回主干通常被称作内合并(Inner merge),如图1.5所示。

有些时候,需要从主干合并代码到缺陷修复分支,通常被称作外合并,如图1.6所示。

图1.5 内合并示例

图1.6 外合并示例

1.3.9 变更集
变更集(Changesets) 是一种可以方便地将一个或多个对代码库的修改组织到一起的方法。大多数支持变更集的源代码管理工具都可以提供应用或者回退变更集的功能。提交变更集(又被称作签入)通常是一个原子事务,这意味着整个变更都可以成功地签入(或出现错误,完全地回退)。我非常感激变更集带来的好处。还记得某个漫长的夜晚,当我试图去提交几千个文件的时候,在签入的中途却停止了的困窘。跟踪哪些文件已经被成功签入和哪些文件在签入中途失败需要再次提交是非常痛苦且容易出错的事。考虑到变更集,一些源代码管理工具提供了管理整个代码库的能力,这样如果不小心失误了,就可以容易地回退。通常可以把一个变更和一个缺陷或者一个需求关联到一起,我们将会在下一节详细讨论具体方法。

1保留签出模型,也被称为悲观锁模型;而非保留签出模型,也被称为乐观锁模型。

时间: 2024-09-19 08:58:35

《配置管理最佳实践》——1.3 源代码管理核心概念的相关文章

《配置管理最佳实践》——1.5 管理全球分布式开发团队

1.5 管理全球分布式开发团队 源代码管理可以帮助协调分布式开发团队之间的工作.如图1.7所示,在伦敦.纽约和孟买有三个开发团队,源代码最佳实践可以有条理有逻辑地帮助协调每个人的工作. 在地理分布式的工作环境中,全球性软件开发的挑战是能够协调好工作和使变更受控.对于同一房间里坐在对面的两个人,协调好工作和使变更受控都不是件很容易的事情,而对于那些身处不同国家,工作在不同时区,有着不同语言.文化.追求的团队来说,这就更难了. 源代码管理可以在各自的分支上帮助组织这些工作,使其可以在一个地方被完成,

《配置管理最佳实践》——导读

** 前言 **配置管理(CM,Configuration Management)在任何开发工作中都起着非常关键的作用.我从事配置管理的实施和支持工作已经超过25年,本书中将讨论的大部分内容都直接来自于个人的经验.我实施并支持过各种配置管理的实践方法并达到这样一种状态--如果建立的过程或自动化没有按照预期般运作的话,我经常会在半夜里被惊醒.作为一名教师,我向超过九百多的专业技术人员传授过工业级的配置管理工具(同样,他们在成功地完成课程后都得到了我家的电话号码,这样如果我没有教授好知识和技能,即使

《配置管理最佳实践》——1.13 结论

1.13  结论 源代码管理是配置管理最佳实践的核心.在保护源代码的同时,利用配置管理工具和规范可提高工作效率和产品质量.在选择源代码管理工具和购买某些源代码管理功能时,一定要小心行事.培训和定义良好的使用模型有助于确保配置管理职能有效地执行且容易被接受.认真对待特殊的需求和满足这种需求时可能发生的风险.支持愿意深入了解源代码管理的人,鼓励他们分享自己的经验.源代码管理是一项团队活动.如果开发人员愿意去学习和分享配置管理最佳实践,源代码管理流程就会更加高效.

《配置管理最佳实践》——1.2 从哪里开始

1.2 从哪里开始 实施源代码管理最好的切入点是确定源代码管理的目标和需求.我曾经工作过的一些公司,有的是集中全公司的资源来做好配置管理:而有的则是源代码管理几乎处于自我管理的状态.大多数公司开始做都是先评估其现有的做法,如确保代码安全.控制变更.建立基线和发布,包括修复补丁.当我们进行评估时,一定要确保现有的实践和进行改进的领域是依然可以工作的.采用一种平稳渐进的改进方式可以帮助避免来自团队的抵制,并且使他们在别人审视自己团队长处和短处时感觉比较舒适.我推荐敏捷和精益的做法.例如,只进行可以让

《配置管理最佳实践》——1.8 培训

1.8 培训 在选择源代码管理工具时,还要考虑供应商或者第三方机构是否有系统性的培训.有时我更倾向于那些非供应商提供的培训,因为我希望从一个没有偏见的角度去了解如何有效地使用工具,尤其是涉及工具缺陷和限制等.供应商有时认为培训只是销售过程的延伸,所以他们的培训总有种推销的味道,不能让人从公正的角度去看工具.我曾经参加过一个培训,这位讲师以前就是在供应商处工作,并且自己确实写了一些代码.他直率地讲了以前代码的一些错误,这些错误很多时候都是由于公司没有给他足够时间导致的,因为那时的首要任务是向外声称

《配置管理最佳实践》——1.12 高级特性和授权高级用户

1.12 高级特性和授权高级用户 配置管理最佳实践很多专业技术人员是源代码管理工具和规范的高级用户,而另外一些人仅仅期望以最少的精力把工作做完就可以了.团队中的每个人并非都要成为一个源代码管理工具专家,但应该认可和授权那些在源代码管理方面想提高的用户.我从同事那里学到很多经验,所以鼓励你授权给那些认真对待配置管理最佳实践且愿意分享所学的专业技术人员.良好的配置管理经验是会传播的,配置管理员应该努力宣扬和弘扬这种传播.

《配置管理最佳实践》——2.10 建立构建过程

2.10 建立构建过程 实施构建工程最佳实践是一项非常具有挑战性的工作.构建工程师可以选择有益于公司的实践:也可以选择最好的工具去建立可重复的构建,实施持续集成.但是实际工作远不止此,构建工程部门还需要为开发团队提供培训和技术支持.我的经验是和研发团队合作,解决构建和部署过程中的问题,然后转到幕后做支持,把日常的工作还交给开发团队来负责.这里有个前提就是公司的合规部门允许这样做.曾经一家实施 SAS-70的公司认为可以接受这样的做法:但是另外一家公司认为这不合规,不能接受.在一些公司里因为合规的

《配置管理最佳实践》——第1章 源代码管理 1.1为什么源代码管理如此重要

第I部分 配置管理核心实践 第1章 源代码管理 源代码管理是保护组装成系统的所有工件(artifact)的学科.源代码管理是配置管理的核心职能(function),直接影响着团队的生产力和产品质量.不幸的是,很多公司并没有意识到建立高效源代码管理机制的重要性,缺乏实施源代码管理的能力,缺少源代码管理工具和流程.这一章将讨论如何正确地进行源代码管理.我曾经负责过多家分布全球的大公司的源代码管理工作.源代码管理必须确保产品发布的源代码永远都不能丢失.源代码需要通过一种灵活和创新的方式进行管理.每个公

《配置管理最佳实践》——2.3 构建工程的核心概念

2.3 构建工程的核心概念 成功的构建工程都包含如下职责:首先构建的依赖关系易被理解且受控,基线是可识别的,在此基础上可重复地生成构建.每次构建都是针对配置项的活动.构建包含配置项,并且可产生新的配置项.几乎构建中的任何东西都可以被认为是配置项.构建工程师的首要任务,是核实所有的可执行文件.重要的脚本.文档和文本文件已被正确地识别和标识. 2.3.1 版本ID和标记可执行文件构建工程师既能轻而易举地识别出源代码基线,也能轻松地确定构建产物的版本.这包括所有的二进制文件(中间代码和运行时模块)以及