{"id":119,"date":"2009-02-02T09:12:32","date_gmt":"2009-02-02T09:12:32","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2009\/02\/02\/best-practices-in-software-configuration-management\/"},"modified":"2017-12-26T00:11:59","modified_gmt":"2017-12-26T00:11:59","slug":"best-practices-in-software-configuration-management","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/best-practices-in-software-configuration-management\/","title":{"rendered":"Best Practices in Software Configuration Management &#8211; SCM Best Practices Guide"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3973 aligncenter\" src=\"http:\/\/www.scmgalaxy.com\/tutorials\/wp-content\/uploads\/2009\/02\/SCM-pRactices.png\" alt=\"scm-best-practices\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2009\/02\/SCM-pRactices.png 600w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2009\/02\/SCM-pRactices-300x200.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p><strong>Best Practices in Software Configuration Management<\/strong><\/p>\n<p><strong>Abstract<\/strong><br \/>\nWhen deploying new SCM (software configuration management) tools,<br \/>\nimplementers sometimes focus on perfecting fine-grained activities, while<br \/>\nunwittingly carrying forward poor, large-scale practices from their previous jobs or<br \/>\nprevious tools. The result is a well-executed blunder. This paper promotes some<br \/>\nhigh-level best practices that reflect the authors\u2019 experiences in deploying SCM.<\/p>\n<p><strong>1. Introduction<\/strong><br \/>\n\u201cA tool is only as good as you use it,\u201d the saying goes<em>. <\/em>As providers of software configuration management (SCM) tools and consultants to software companies, we<br \/>\nare often asked for sound advice on SCM best practices \u2013 that is, how to deploy SCM software to the maximum advantage. In answering these requests we have a bounty of direct and indirect SCM experience from which to draw. The direct experience comes from having been developers and codeline managers ourselves; the indirect experience comes from customer reports of successes and failures with our product (Perforce) and other SCM tools.<br \/>\nThe table below lists six general areas of SCM deployment, and some coarse-grained best practices within each of those areas. The following chapters explain each item.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"319\"><strong>Workspaces, <\/strong>where<br \/>\ndevelopers build, test, and<br \/>\ndebug.<\/td>\n<td valign=\"top\" width=\"319\">\u00b7 Don\u2019t share workspaces.<br \/>\n\u00b7 Don\u2019t work outside of managed workspaces.<br \/>\n\u00b7 Don\u2019t use jello views.<br \/>\n\u00b7 Stay in sync with the codeline.<br \/>\n\u00b7 Check in often.<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"319\"><strong>Codelines, <\/strong>the canonical sets<br \/>\nof source files.<\/td>\n<td valign=\"top\" width=\"319\">\u00b7 Give each codeline a policy.<br \/>\n\u00b7 Give each codeline an owner.<br \/>\n\u00b7 Have a mainline.<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"319\"><strong>Branches, <\/strong>variants of the<br \/>\ncodeline.<\/td>\n<td valign=\"top\" width=\"319\">\u00b7 Branch only when necessary.<br \/>\n\u00b7 Don\u2019t copy when you mean to branch.<br \/>\n\u00b7 Branch on incompatible policy.<br \/>\n\u00b7 Branch late.<br \/>\n\u00b7 Branch, instead of freeze.<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"319\"><strong>Change propagation, <\/strong>getting<br \/>\nchanges from one codeline to<br \/>\nanother.<\/td>\n<td valign=\"top\" width=\"319\">\u00b7 Make original changes in the branch that has<br \/>\nevolved the least since branching.<br \/>\n\u00b7 Propagate early and often.<br \/>\n\u00b7 Get the right person to do the merge.<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"319\"><strong>Builds, <\/strong>turning source files<br \/>\ninto products.<\/td>\n<td valign=\"top\" width=\"319\">\u00b7 Source + tools = product.<br \/>\n\u00b7 Check in all original source.<br \/>\n\u00b7 Segregate built objects from original source.<br \/>\n\u00b7 Use common build tools.<br \/>\n\u00b7 Build often.<br \/>\n\u00b7 Keep build logs and build output.<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"319\"><strong>Process, <\/strong>the rules for all of<br \/>\nthe above.<\/td>\n<td valign=\"top\" width=\"319\">\u00b7 Track change packages.<br \/>\n\u00b7 Track change package propagations.<br \/>\n\u00b7 Distinguish change requests from change<br \/>\npackages.<br \/>\n\u00b7 Give everything and owner.<br \/>\n\u00b7 Use living documents.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>2. The Workspace<\/strong><br \/>\nThe workspace is where engineers edit source files, build the software components they\u2019re working on, and test and debug what they\u2019ve built. Most SCM systems have some notion of a workspace; sometimes they are called \u201csandboxes\u201d, as in Source Integrity, or \u201cviews\u201d, as in ClearCase and Perforce. Changes to managed SCM repository files begin as changes to files in a workspace. The best practices for workspaces include:\u00b7 <em>Don\u2019t share workspaces. <\/em>A workspace should have a single purpose, such as an edit\/build\/test area for a single developer, or a build\/test\/release area for a product release. Sharing workspaces confuses people, just as sharing a desk does. Furthermore, sharing workspaces compromises the SCM system\u2019s ability to track activity by user or task. Workspaces and the disk space they occupy are cheap; don\u2019t waste time trying to conserve them.\u00b7 <em>Don\u2019t work outside of managed workspaces. <\/em>Your SCM system can only track work in progress when it takes place within managed workspaces. Users working outside of workspaces are beached; there\u2019s a river of information flowing past and they\u2019re not part of it. For instance, SCM systems generally use workspaces to facilitate some of the communication among developers working on related tasks. You can see what is happening in others\u2019 workspaces, and they can see what\u2019s going on in yours. If you need to take an emergency vacation, your properly managed workspace may be all you can leave behind. Use proper workspaces.<br \/>\n\u00b7 <em>Don\u2019t use jello views. <\/em>A file in your workspace should not change unless <em>you<\/em><em>explicitly <\/em>cause the change. A \u201cjello view\u201d is a workspace where file changes are<br \/>\ncaused by external events beyond your control. A typical example of a jello view is a workspace built upon a tree of symbolic links to files in another workspace \u2013<br \/>\nwhen the underlying files are updated, your workspace files change. Jello views are a source of chaos in software development. Debug symbols in executables<br \/>\ndon\u2019t match the source files, mysterious recompilations occur in supposedly trivial rebuilds, and debugging cycles never converge \u2013 these are just some of the<br \/>\nproblems. Keep your workspaces firm and stable by setting them up so that users have control over when their files change.\u00b7 <em>Stay in sync with the codeline. <\/em>As a developer, the quality of your work depends on how well it meshes with other peoples\u2019 work. In other words, as changes are checked into the codeline, you should update your workspace and integrate those changes with yours. As an SCM engineer, it behooves you to make sure this workspace update operation is straightforward and unencumbered with tricky or time-consuming procedures. If developers find it fairly painless to update their workspaces, they\u2019ll do it more frequently and integration problems won\u2019t pile up at project deadlines.<br \/>\n\u00b7 <em>Check in often. <\/em>Integrating your development work with other peoples\u2019 work also requires you to check in your changes as soon as they are ready. Once you\u2019ve<br \/>\nfinished a development task, check in your changed files so that your work is available to others. Again, as the SCM engineer, you should set up procedures that encourage frequent check-ins. Don\u2019t implement unduly arduous validation procedures, and don\u2019t freeze codelines (see Branching, below). Short freezes are bearable, but long freezes compromise productivity. Much productivity can be wasted waiting for the right day (or week, or month) to submit changes.<\/p>\n<p><strong>3. The Codeline<\/strong><br \/>\nIn this context, the codeline is the canonical set of source files required to produce your software. Typically codelines are branched, and the branches evolve into variant<br \/>\ncodelines embodying different releases. The best practices with regard to codelines are:<br \/>\n\u00b7 <em>Give each codeline a policy. <\/em>A codeline policy specifies the fair use and permissible check-ins for the codeline, and is the essential user\u2019s manual for<br \/>\ncodeline SCM. For example, the policy of a development codeline should state that it isn\u2019t for release; likewise, the policy of a release codeline should limit<br \/>\nchanges to approved bug fixes.1 The policy can also describe how to document changes being checked in, what review is needed, what testing is required, and<br \/>\nthe expectations of codeline stability after check-ins. A policy is a critical component for a documented, enforceable software development process, and a<br \/>\ncodeline without a policy, from an SCM point of view, is out of control.\u00b7 <em>Give each codeline an owner. <\/em>Having defined a policy for a codeline, you\u2019ll soon<br \/>\nencounter special cases where the policy is inapplicable or ambiguous. Developers facing these ambiguities will turn to the person in charge of the<br \/>\ncodeline for workarounds. When no one is in charge, developers tend to enact their own workarounds without documenting them. Or they simply procrastinate<br \/>\nbecause they don\u2019t have enough information about the codeline to come up with a reasonable workaround. You can avoid this morass by appointing someone to<br \/>\nown the codeline, and to shepherd it through its useful life. With this broader objective, the codeline owner can smooth the ride over rough spots in software<br \/>\ndevelopment by advising developers on policy exceptions and documenting them.<\/p>\n<p>\u00b7 <em>Have a mainline. <\/em>A \u201cmainline,\u201d or \u201ctrunk,\u201d is the branch of a codeline that evolves forever. A mainline provides an ultimate destination for almost all<br \/>\nchanges \u2013 both maintenance fixes and new features \u2013 and represents the primary, linear evolution of a software product. Release codelines and development<br \/>\ncodelines are branched from the mainline, and work that occurs in branches is propagated back to the mainline.<\/p>\n<p>IMAGE \u00a0&#8211; 1<\/p>\n<p>Figure 1 shows a mainline (called \u201cmain\u201d), from which several release lines (\u201cver1\u201d, \u201cver2\u201d and \u201cver3\u201d) and feature development lines (\u201cprojA\u201d, \u201cprojb\u201d, and<br \/>\n\u201cprojC\u201d) have been branched. Developers work in the mainline or in a feature development line. The release lines are reserved for testing and critical fixes, and<br \/>\nare insulated from the hubbub of development. Eventually all changes submitted to the release lines and the feature development lines get merged into the<br \/>\nmainline. The adverse approach is to \u201cpromote\u201d codelines; for example, to promote a development codeline to a release codeline, and branch off a new development<br \/>\ncodeline. For example, Figure 2 shows a development codeline promoted to a release codeline (\u201cver1\u201d) and branched into another development codeline<br \/>\n(\u201cprojA\u201d). Each release codeline starts out as a development codeline, and development moves from codeline to codeline.<\/p>\n<p>IMAGE &#8211; 2<\/p>\n<p>The promotion scheme suffers from two crippling drawbacks: (1) it requires the policy of a codeline to change, which is never easy to communicate to everyone;<br \/>\n(2) it requires developers to relocate their work from one codeline to another, which is error-prone and time-consuming. <em>90% of SCM \u201cprocess\u201d is enforcing<\/em><br \/>\n<em>codeline promotion to compensate for the lack of a mainline.<\/em> Process is streamlined and simplified when you use a mainline model<em>. <\/em>With a<br \/>\nmainline, contributors\u2019 workspaces and environments are stable for the duration of their tasks at hand, and no additional administrative overhead is incurred as<br \/>\nsoftware products move forward to maturity.<\/p>\n<p><strong>4. Branching<\/strong><br \/>\nBranching, the creation of variant codelines from other codelines, is the most problematic area of SCM. Different SCM tools support branching in markedly<br \/>\ndifferent ways, and different policies require that branching be used in still more different ways. We found the following guidelines helpful when branching (and<br \/>\nsometimes when avoiding branching):\u00b7<\/p>\n<p><em>Branch only when necessary. <\/em>Every branch is more work \u2013 more builds, more changes to be propagated among codelines, more source file merges. If you keep this in mind every time you consider making a branch you may avoid sprouting unnecessary branches.<br \/>\n\u00b7 <em>Don\u2019t copy when you mean to branch. <\/em>An alternative to using your SCM tool\u2019s branching mechanism is to copy a set of source files from one codeline and<br \/>\ncheck them in to another as new files. Don\u2019t think that you can avoid the costs of branching by simply copying. Copying incurs all the headaches of branching \u2013<br \/>\nadditional entities and increased complexity \u2013 but without the benefit of your SCM system\u2019s branching support. Don\u2019t be fooled: even \u201cread-only\u201d copies<br \/>\nshipped off to another development group \u201cfor reference only\u201d often return with changes made. Use your SCM system to make branches when you spin off parts<br \/>\nor all of a codeline.<br \/>\n\u00b7 <em>Branch on incompatible policy. <\/em>There is one simple rule to determine if a codeline should be branched: it should be branched when its users need different<br \/>\ncheck-in policies. For example, a product release group may need a check-in policy that enforces rigorous testing, whereas a development team may need a<br \/>\npolicy that allows frequent check-ins of partially tested changes. This policy divergence calls for a codeline branch. When one development group doesn\u2019t<br \/>\nwish to see another development group\u2019s changes, that is also a form of incompatible policy: each group should have its own branch.<br \/>\n\u00b7 <em>Branch late. <\/em>To minimize the number of changes that need to be propagated from one branch to another, put off creating a branch as long as possible. For<br \/>\nexample, if the mainline branch contains all the new features ready for a release, do as much testing and bug fixing in it as you can before creating a release<br \/>\nbranch. Every bug fixed in the mainline before the release branch is created is one less change needing propagation between branches.<br \/>\n\u00b7 <em>Branch instead of freeze. <\/em>On the other hand, if testing requires freezing a codeline, developers who have pending changes will have to sit on their changes<br \/>\nuntil the testing is complete. If this is the case, branch the codeline early enough so that developers can check in and get on with their work.<\/p>\n<p><strong>5. Change Propagation<\/strong><br \/>\nOnce you have branched codelines, you face the chore of propagating file changes across branches. This is rarely a trivial task, but there are some things you can do to<br \/>\nkeep it manageable.<br \/>\n\u00b7 <em>Make original changes in the branch that has evolved the least since branching.<\/em> It is much easier to merge a change from a file that is close to the common<br \/>\nancestor than it is to merge a change from a file that has diverged considerably. This is because the change in the file that has diverged may be built upon<br \/>\nchanges that are not being propagated, and those unwanted changes can confound the merge process. You can minimize the merge complexity by making<br \/>\noriginal changes in the branch that is the most stable. For example, if a release codeline is branched from a mainline, make a bug fix first in the release line and<br \/>\nthen merge it into the mainline. If you make the bug fix in the mainline first, subsequently merging it into a release codeline may require you to <em>back out<\/em><br \/>\nother, incompatible changes that aren\u2019t meant to go into the release codeline.<br \/>\n\u00b7 <em>Propagate early and often. <\/em>When it\u2019s feasible to propagate a change from one branch to another (that is, if the change wouldn\u2019t violate the target branch\u2019s<br \/>\npolicy), do it sooner rather than later. Postponed and batched change propagations can result in stunningly complex file merges.<br \/>\n\u00b7 <em>Get the right person to do the merge. <\/em>The burden of change propagation can be lightened by assigning the responsibility to the engineer best prepared to resolve<br \/>\nfile conflicts. Changes can be propagated by (a) the owner of the target files, (b) the person who make the original changes, or (c) someone else. Either (a) or (b)<br \/>\nwill do a better job than (c).<\/p>\n<p><strong>6. Builds<\/strong><br \/>\nA build is the business of constructing usable software from original source files. Builds are more manageable and less prone to problems when a few key practices are<br \/>\nobserved:<br \/>\n\u00b7 <em>Source + tools = product. <\/em>The only ingredients in a build should be source files and the tools to which they are input. Memorized procedures and yellow stickies<br \/>\nhave no place in this equation. Given the same source files and build tools, the resulting product should always be the same. If you have rote setup procedures,<br \/>\nautomate them in scripts. If you have manual setup steps, document them in build instructions. And document all tool specifications, including OS, compilers, include files, link libraries, make programs, and executable paths.<br \/>\n\u00b7 <em>Check in <\/em>all <em>original source. <\/em>When software can\u2019t be reliably reproduced from the same ingredients, chances are the ingredient list is incomplete. Frequently<br \/>\noverlooked ingredients are makefiles, setup scripts, build scripts, build instructions, and tool specifications. All of these are the source you build with.<br \/>\nRemember: <em>source + tools = product.<\/em><br \/>\n\u00b7 <em>Segregate built objects from original source. <\/em>Organize your builds so that the directories containing original source files are not polluted by built objects<em>.<\/em><br \/>\nOriginal source files are those you create \u201cfrom an original thought process\u201d with a text editor, an application generator, or any other interactive tool. Built objects<br \/>\nare all the files that get created during your build process, including generated source files. Built objects should not go into your source code directories.<br \/>\nInstead, build them into a directory tree of their own. This segregation allows you to limit the scope of SCM-managed directories to those that contain only<br \/>\nsource. It also corrals the files that tend to be large and\/or expendable into one location, and simplifies disk space management for builds.<br \/>\n\u00b7 <em>Use common build tools. <\/em>Developers, test engineers, and release engineers should all use the same build tools. Much time is wasted when a developer<br \/>\ncannot reproduce a problem found in testing, or when the released product varies from what was tested. Remember: <em>source + tools = product.<\/em><br \/>\n\u00b7 <em>Build often. <\/em>Frequent, end-to-end builds with regression testing (\u201csanity\u201d builds) have two benefits: (1) they reveal integration problems introduced by check-ins,<br \/>\nand (2) they produce link libraries and other built objects that can be used by developers. In an ideal world, sanity builds would occur after every check-in, but<br \/>\nin an active codeline it\u2019s more practical to do them at intervals, typically nightly. Every codeline branch should be subject to regular, frequent, and complete builds<br \/>\nand regression testing, even when product release is in the distant future.<br \/>\n\u00b7 <em>Keep build logs and build outputs. <\/em>For any built object you produce, you should be able to look up the exact operations (e.g., complete compiler flag and link<br \/>\ncommand text) that produced the last known good version of it. Archive build outputs and logs, including source file versions (e.g., a label), tool and OS<br \/>\nversion info, compiler outputs, intermediate files, built objects, and test results, for future reference. As large software projects evolve, components are handed<br \/>\noff from one group to another, and the receiving group may not be in a position to begin builds of new components immediately. When they do begin to build<br \/>\nnew components, they will need access to previous build logs in order to diagnose the integration problems they encounter.<\/p>\n<p><strong>7. Process<\/strong><br \/>\nIt would take an entire paper, or several papers, to explore the full scope of SCM process design and implementation, and many such papers have already been written. Furthermore, your shop has specific objectives and requirements that will be reflected in the process you implement, and we do not presume to know what those are. In our experience, however, some process concepts are key to any SCM implementation:<br \/>\n\u00b7 <em>Track change packages. <\/em>Even though each file in a codeline has its revision history, each revision in its history is only useful in the context of a set of related<br \/>\nfiles. The question \u201cWhat other source files were changed along with this particular change to foo.c?\u201d can\u2019t be answered unless you track change<br \/>\n<em>packages<\/em>, or sets of files related by a logical change. Change packages, not individual file changes, are the visible manifestation of software development.<br \/>\nSome SCM systems track change packages for you; if yours doesn\u2019t, write an interface that does.<br \/>\n\u00b7 <em>Track change package propagations. <\/em>One clear benefit of tracking change packages is that it becomes very easy propagate logical changes (e.g., bug fixes)<br \/>\nfrom one codeline branch to another. However, it\u2019s not enough to simply propagate change packages across branches; you must keep track of which<br \/>\nchange packages have been propagated, which propagations are pending, and which codeline branches are likely donors or recipients of propagations.<br \/>\nOtherwise you\u2019ll never be able to answer the question \u201cIs the fix for bug X in the release Y codeline?\u201d Again, some SCM systems track change package<br \/>\npropagations for you, whereas with others you\u2019ll have to write your own interface to do it. Ultimately, you should never have to resort to \u201cdiffing\u201d files to<br \/>\nfigure out if a change package has been propagated between codelines.<\/p>\n<p>\u00b7 <em>Distinguish change requests from change packages. <\/em>\u201cWhat to do\u201d and \u201cwhat was done\u201d are different data entities. For example, a bug report is a \u201cwhat to do\u201d<br \/>\nentity and a bug fix is a \u201cwhat was done\u201d entity. Your SCM process should distinguish between the two, because in fact there can be a one-to-many<br \/>\nrelationship between change requests and change packages.<br \/>\n\u00b7 <em>Give everything an owner. <\/em>Every process, policy, document, product, component, codeline, branch, and task in your SCM system should have an<br \/>\nowner. Owners give life to these entities by representing them; an entity with an owner can grow and mature. Ownerless entities are like obstacles in an ant trail<br \/>\n\u2013 the ants simply march around them as if they weren\u2019t there.<br \/>\n\u00b7 <em>Use living documents. <\/em>The policies and procedures you implement should be described in living documents; that is, your process documentation should be as<br \/>\nreadily available and as subject to update as your managed source code. Documents that aren\u2019t accessible are useless; documents that aren\u2019t updateable<br \/>\nare nearly so. Process documents should be accessible from all of your development environments: at your own workstation, at someone else\u2019s<br \/>\nworkstation, and from your machine at home. And process documents should be easily updateable, and updates should be immediately available.<\/p>\n<p><strong>8. Conclusion<\/strong><br \/>\nBest practices in SCM, like best practices anywhere, always seem obvious once you\u2019ve used them. The practices discussed in this paper have worked well for us, but<br \/>\nwe recognize that no single, short document can contain them all. So we have presented the practices that offer the greatest return and yet seem to be violated more<br \/>\noften than not. We welcome the opportunity to improve this document, and solicit both challenges to the above practices as well as the additions of new ones.<\/p>\n<p><strong>10. References<\/strong><br \/>\nBerczuk, Steve. &#8220;Configuration Management Patterns&#8221;, 1997. Available at<br \/>\nhttp:\/\/www.bell-labs.com\/cgi-user\/OrgPatterns\/OrgPatterns?ConfigurationManagementPatterns.<br \/>\nCompton, Stephen B, <em>Configuration Management for Software<\/em>, VNR Computer<br \/>\nLibrary, Van Nostrand Reinhold, 1993.<br \/>\nContinuus Software Corp., \u201cWork Area Management\u201d, <em>Continuus\/CM: Change<\/em><br \/>\n<em>Management for Software Development. <\/em>Available at<br \/>\nhttp:\/\/www.continuus.com\/developers\/developersACE.html.<br \/>\nDart, Susan, &#8220;Spectrum of Functionality in Configuration Management Systems&#8221;,<br \/>\nSoftware Engineering Institute, 1990. Available at<br \/>\n<a href=\"http:\/\/www.sei.cmu.edu\/technology\/case\/scm\/tech_rep\/TR11_90\/TOC_TR11_90.html\" target=\"_blank\" rel=\"noopener\">http:\/\/www.sei.cmu.edu\/technology\/case\/scm\/tech_rep\/TR11_90\/TOC_TR11_90.html<\/a><\/p>\n<p>Jameson, Kevin, <em>Multi Platform Code Management<\/em>, O&#8217;Reilly &amp; Associates, 1994<br \/>\nLinenbach, Terris, &#8220;Programmers&#8217; Canvas: A pattern for source code management&#8221;<br \/>\n1996. Available at http:\/\/www.rahul.net\/terris\/ProgrammersCanvas.htm.<br \/>\nLyon, David D, <em>Practical CM<\/em>, Raven Publishing, 1997<br \/>\nMcConnell, Steve, &#8220;Best Practices: Daily Build and Smoke Test&#8221;,<br \/>\n<em>IEEE Software<\/em>, Vol. 13, No. 4, July 1996<br \/>\nvan der Hoek, Andre, Hall, Richard S., Heimbigner, Dennis, and Wolf, Alexander L.,<br \/>\n&#8220;Software Release Management&#8221;, <em>Proceedings of the 6th European Software<\/em><br \/>\n<em>Engineering Conference<\/em>, Zurich, Switzerland, 1997.<\/p>\n<p><strong>10. Author<\/strong><\/p>\n<p>Laura Wingerd<br \/>\nPerforce Software, Inc.<br \/>\nwingerd@perforce.com<br \/>\nChristopher Seiwald<br \/>\nPerforce Software, Inc.<br \/>\nseiwald@perforce.com<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Best Practices in Software Configuration Management Abstract When deploying new SCM (software configuration management) tools, implementers sometimes focus on perfecting fine-grained activities, while unwittingly carrying forward poor, large-scale practices from&#8230; <\/p>\n","protected":false},"author":1,"featured_media":3973,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[647,1652,2929,282,1517,2931,2709,1122,2933,507,244,2708,2934,2512,2928,2937,2935,2972,2936,2932,179,2435,2930,1023,1593,213,670],"class_list":["post-119","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorised","tag-best","tag-best-practices","tag-best-practices-in-scm","tag-configuration","tag-configuration-management","tag-good","tag-good-practices","tag-guide","tag-ideal","tag-list","tag-management","tag-practices","tag-recomended","tag-right","tag-scm-best-practices","tag-scm-best-practices-guide","tag-scm-best-practices-techniques","tag-scm-best-practices-tips","tag-scm-best-practices-tutorial","tag-scm-good-practices","tag-software","tag-software-configuration-management","tag-software-configuration-management-best-practices","tag-software-development","tag-techniques","tag-tutorial","tag-what"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"predecessor-version":[{"id":3975,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions\/3975"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/3973"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}