<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; 主干开发</title>
	<atom:link href="https://www.phppan.com/tag/%e4%b8%bb%e5%b9%b2%e5%bc%80%e5%8f%91/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 25 Apr 2026 00:56:17 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>无分支开发</title>
		<link>https://www.phppan.com/2012/01/no-branch/</link>
		<comments>https://www.phppan.com/2012/01/no-branch/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 00:53:38 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[项目管理]]></category>
		<category><![CDATA[主干开发]]></category>
		<category><![CDATA[分支开发]]></category>
		<category><![CDATA[版本管理]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1563</guid>
		<description><![CDATA[在一个代码库上创建分支的能力是版本控制系统最重要的特性。它的作用是创建一个副本，并将在这个副本上进行操作，从此 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>在一个代码库上创建分支的能力是版本控制系统最重要的特性。它的作用是创建一个副本，并将在这个副本上进行操作，从此它就有了它自己的发展方向，也许有一天会回来，回来时就会合并。分支的作用就是为了更好的帮助并行开发，即在同一时刻能够在两个或更多的工作流上面开发，而不会相互影响。分支开会可以用于哪些应用场景呢？</p>
<style>
.entry p {margin:13px 5px 0 5px;}
</style>
<p>假设我们现在使用的是SVN，并且都是在主干上开发，此时A项目组下在开发，而B项目组准备发布，并且两个项目组中间有一些公共的代码，这个时候就产生了B项目组发布对于A项目组的时间依赖。此时分支开发是一种解决方案。</p>
<p>常见的分支方法有两种：</p>
<ol>
<li>在开发时分支。针对不同的项目或开发团队做分支操作，每个项目或开发团队有一个副本，其所有的操作都在副本上进行，在发布时将分支合并到主干，做整体的合并集成，并做整体发布。这是先分后合的招式。
</li>
<li>在发布时分支。主干上开发完成发布后，创建分支，在分支上修改BUG，当修改的BUG发布时将修改的内容合并到主干。这是先合后分再合的招式。
</li>
</ol>
<p>分支是基于并行开发的一种理想状态，即各个分支是完全独立存在的，并且互不干扰，各成系统。但是现实是各个分支基本上都是有一些关联或依赖的。在开发时可能没有感觉，但是当需要将分支的内容合并时，就会产生较多的冲突和问题，虽然现在的版本控制系统已经在这个方面做得相当好了，但是实际操作中还是会存在一些问题，还是会花费较多的时间。因此在做分支开发时，通常会建议以尽可能高的频率将分支的代码合并到主干净，并且确保主干的正常运行，这样会在一定程序上减缓最终实施合并时的冲突。</p>
<p>什么是无分支开发呢？所谓无分支开发就是指所有的开发工作都在主干上进行，当然这是一种理想情况，但是我们可以尽可能向它靠拢。如果实施了无分支开发，此时就不会存在分支、合并、解决合并冲突等问题了，解决合并冲突的问题最好的方法就是永远不要合并，这和赌博不输的最好的办法就是永远不赌一样。为什么说这是理想情况呢？因为在我们的项目中存在大量的依赖，一个文件或一个类，甚至一个函数可能会被多个人或多个团队修改，如果是多个团队的多个项目并行的话，这咱依赖关系将会影响项目的发布。那么怎么减少这些依赖，嗯，是减少，因为我们基本不可能完全去掉这种依赖，这和我们写代码一样，一些有必要的耦合是完全存在的，并且有其存在的必要性。</p>
<ol>
<li>迪米特法则。迪米特法则（Law of Demeter）又叫作最少知识原则（Least Knowledge Principle 简写LKP），”不要和陌生人说话“，也就是说一个对象应当对其他对象有尽可能少的了解。这是到类级，对象级别的讲究。
</li>
<li>
减小需求的粒度。以一种更加敏捷的方式实现需求，将大的需求分割成小的需求，以增量的方式实现并发布。
</li>
<li>
使用通过抽象来模拟分支的方式实现代码库中大范围的变更。
</li>
<li>
对于公共部分做到文件级的版本发布。即一次发布多个文件的多个版本。
</li>
<li>
使用模块和组件，从功能、团队或变更频率等角度对代码进行切割，以解耦代码间的依赖.
</li>
<li>
将新功能隐藏起来，直到它完成。
</li>
</ol>
<p>以上的几点更适合于小规模团队。</p>
<p>关于第一点，这是面向对象设计的重要原则之一，除此之外，我们经常还会念叨开闭原则，KISS等等。这些都是实现无分支开发时代码级的一些优化措施。</p>
<p>关于第二点，将大的需求变为小的需求本身就是一个比较困难的工作，拆分的原则是什么？粒度以多大 为优，这些都需要依据实现的情况进行判断，以周为单位？以页面为单位？这种方式会比较轻，可以随时停下，即使需求方向有问题，我们也是可以在较少损失的情况下调头。如果我们坚持这样做，那么就意味着我们在解决一个问题：保持应用的持续可工作。</p>
<p>关于第三点，通过抽象来模拟分支的实现步骤如下：</p>
<ol>
<li>
当需求分解后还是无法增量开发或增量开发无法解决问题时，考虑引入中间层或抽象层。使要修改的部分与调用者分离，使其直接低耦合。
</li>
<li>
在需要修改的那部分系统代码上创建一个抽象层。
</li>
<li>
重构系统的其他部分，让他使用这个抽象层。
</li>
<li>
创建一种新的实现代码，在它完成之前不要将它作为产品代码的一部分。
</li>
<li>
更新抽象层，让他使用这个新的实现代码。(如果没有完善的回滚机制，建议在此处做切换开关，即以一个变量控制抽象层的实现，当然，这并不是一个优雅的解决方案)。
</li>
<li>
移除原来的实现代码
</li>
<li>
如果不再需要抽象层，就移除它。
</li>
</ol>
<p>关于第四点，对于公共部分的代码，其修改频率较之其它功能模块更频繁，并且可能存在需要发布旧版本的需求。</p>
<p>关于第五点，模块化，组件化在架构设计中现在已经是非常普遍的行为，但是要想完全模块化或组件化，其难度较大，尽可能的向这方面靠拢，以一定的规则划分模块，针对模块进行设计实现，并在最后将所有模块的结果有机的结合起来。这是在设计层面的分支和合并操作的替代品。</p>
<p>关于第六点，将新功能隐藏起来，直到它完成。这是在没有增量式发布，小步快跑的前提下，或需求确实无法拆分，一组特性一定要一起实现，此时通常会开一个分支做这些新功能的发布，而无分支开发中，可以将这部分代码放在主干，但这些功能对用户不可见，以某种配置项（文件或数据库都行）的方式来操作其对用户的可见性。</p>
<p>读<strong>《持续交付》</strong>总结一</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2012/01/no-branch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
