{"id":119,"date":"2026-10-12T09:01:36","date_gmt":"2026-10-12T09:01:36","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2009\/02\/02\/best-practices-in-software-configuration-management\/"},"modified":"2026-10-12T09:01:37","modified_gmt":"2026-10-12T09:01:37","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":"Software Configuration Management Best Practices: Workspaces, Branches, Builds, and Process Control"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Software configuration management (SCM) is the discipline that keeps source code, branches, builds, and releases coherent as teams and systems grow. This guide is for DevOps engineers, release managers, and technical leads who want fewer integration failures, faster recovery from defects, and reliable delivery workflows.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Originally published on 2009-02-02; fully revised and updated.<\/em><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2009\/02\/SCM-pRactices.png\" alt=\"Software configuration management best practices overview\"\/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">SCM best practices at a glance<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Practice area<\/th><th>Why it matters<\/th><th>Core practices<\/th><\/tr><\/thead><tbody><tr><td>Workspaces<\/td><td>Prevents hidden drift and local chaos<\/td><td>Do not share workspaces, stay inside managed workspaces, sync often, check in often<\/td><\/tr><tr><td>Codelines<\/td><td>Creates predictable collaboration boundaries<\/td><td>Define policy, assign an owner, keep a long-lived mainline<\/td><\/tr><tr><td>Branches<\/td><td>Controls complexity and merge cost<\/td><td>Branch only when needed, branch on policy differences, branch late, avoid copy-as-branch<\/td><\/tr><tr><td>Change propagation<\/td><td>Keeps fixes flowing safely across lines<\/td><td>Make original changes in least-diverged branch, propagate early, assign qualified mergers<\/td><\/tr><tr><td>Builds<\/td><td>Ensures reproducibility and release confidence<\/td><td>Source plus tools equals product, segregate outputs, build often, retain logs and artifacts<\/td><\/tr><tr><td>Process<\/td><td>Preserves traceability and accountability<\/td><td>Track change packages, track propagations, separate requests from implementations, assign ownership<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">End-to-end SCM workflow<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The workflow below captures the operating model implied by the original guidance: controlled workspaces, policy-based codelines, frequent integration, and explicit traceability.<\/p>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Developer updates managed workspace] --> B[Sync with active codeline]\n    B --> C[Implement change package]\n    C --> D[Run local build and tests]\n    D --> E[Submit to mainline or branch]\n    E --> F[CI sanity build and checks]\n    F --> G{Policy compatible across lines}\n    G -- yes --> H[Propagate change early]\n    G -- no --> I[Keep isolated branch policy]\n    H --> J[Record logs artifacts and propagation]\n    I --> J\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Workspace discipline: where quality starts<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Do not share workspaces.<\/strong> One workspace should serve one purpose and one owner.<\/li><li><strong>Do not work outside managed workspaces.<\/strong> Unmanaged edits bypass traceability and team visibility.<\/li><li><strong>Avoid unstable views.<\/strong> Files should not change unless the user intentionally updates them.<\/li><li><strong>Stay in sync with the codeline.<\/strong> Frequent updates reduce large integration shocks.<\/li><li><strong>Check in often.<\/strong> Small, frequent integrations lower merge risk and reduce waiting.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Codeline governance and ownership<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every codeline should have a written policy and an accountable owner. Policy answers what can be submitted, what review and testing are required, and what stability guarantees contributors should expect.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Model<\/th><th>How it works<\/th><th>Strengths<\/th><th>Trade-offs<\/th><\/tr><\/thead><tbody><tr><td>Mainline model<\/td><td>Long-lived trunk receives most propagated changes from feature and release lines<\/td><td>Stable developer environments, simpler long-term flow, clearer destination for fixes and features<\/td><td>Requires disciplined merge and policy enforcement<\/td><\/tr><tr><td>Codeline promotion model<\/td><td>Development line is promoted to release, then a new development line is created<\/td><td>Can match short-term milestone transitions<\/td><td>Policy changes are harder to communicate and teams may need disruptive workspace relocations<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Branching and change propagation without chaos<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Branch only when necessary.<\/strong> Each branch adds build, merge, and coordination cost.<\/li><li><strong>Do not copy when you mean to branch.<\/strong> Manual copies keep the pain but lose SCM intelligence.<\/li><li><strong>Branch on incompatible policy.<\/strong> Different submission rules are a strong reason to branch.<\/li><li><strong>Branch late when possible.<\/strong> Fewer pre-branch changes means fewer future propagations.<\/li><li><strong>Branch instead of long freezes.<\/strong> Extended freezes stall productivity and hide risk.<\/li><li><strong>Propagate early and often.<\/strong> Small merges are safer than large batches.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Example (Git) mapping for frequent sync, focused feature work, and explicit propagation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\">git <span class=\"hljs-keyword\">switch<\/span> main\ngit pull --rebase\ngit <span class=\"hljs-keyword\">switch<\/span> -c feature\/JIRA<span class=\"hljs-number\">-142<\/span>-fix-timeout\n<span class=\"hljs-comment\"># edit and test<\/span>\ngit add src\/worker.py tests\/test_worker.py\ngit commit -m <span class=\"hljs-string\">\"JIRA-142: fix timeout handling in retry loop\"<\/span>\ngit push -u origin feature\/JIRA<span class=\"hljs-number\">-142<\/span>-fix-timeout<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># apply urgent fix first in the least-diverged branch<\/span>\ngit <span class=\"hljs-keyword\">switch<\/span> release\/<span class=\"hljs-number\">2.4<\/span>\ngit cherry-pick a1b2c3d4\ngit push\n\n<span class=\"hljs-comment\"># propagate early to mainline<\/span>\ngit <span class=\"hljs-keyword\">switch<\/span> main\ngit cherry-pick a1b2c3d4\ngit push<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Reproducible builds: source plus tools equals product<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Check in all original build inputs, including scripts and build instructions.<\/li><li>Keep generated artifacts separate from original source directories.<\/li><li>Use common tooling across development, test, and release engineering.<\/li><li>Run frequent full builds with regression checks.<\/li><li>Archive build logs, metadata, and outputs for diagnosis and handoff.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Example build script pattern for auditability:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\">#!\/usr\/bin\/env bash<\/span>\nset -euo pipefail\n\nBUILD_ID=<span class=\"hljs-string\">\"$(date +%Y%m%d-%H%M%S)\"<\/span>\nOUT_DIR=<span class=\"hljs-string\">\"build\/${BUILD_ID}\"<\/span>\nmkdir -p <span class=\"hljs-string\">\"${OUT_DIR}\"<\/span>\n\ngit rev-parse HEAD | tee <span class=\"hljs-string\">\"${OUT_DIR}\/revision.txt\"<\/span>\nuname -a | tee <span class=\"hljs-string\">\"${OUT_DIR}\/os.txt\"<\/span>\ngo version | tee <span class=\"hljs-string\">\"${OUT_DIR}\/toolchain.txt\"<\/span>\n\nmake clean\nmake all | tee <span class=\"hljs-string\">\"${OUT_DIR}\/build.log\"<\/span>\nmake test | tee <span class=\"hljs-string\">\"${OUT_DIR}\/test.log\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Process controls that make SCM scalable<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Track change packages<\/strong> (logical units of work), not only individual file revisions.<\/li><li><strong>Track propagation status<\/strong> across codelines so release readiness is answerable.<\/li><li><strong>Separate change requests from delivered changes.<\/strong> A request and its implementation are different records.<\/li><li><strong>Assign ownership everywhere.<\/strong> Policies, branches, components, and documents need accountable maintainers.<\/li><li><strong>Use living documents.<\/strong> Process docs should be easy to access and update from normal engineering environments.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Example policy record (tool-agnostic YAML):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-yaml\">codeline: release<span class=\"hljs-number\">-2.4<\/span>\n<span class=\"hljs-attr\">owner<\/span>: release-manager\n<span class=\"hljs-attr\">policy<\/span>:\n  allowed_changes:\n    - approved_bugfix\n  <span class=\"hljs-attr\">require_review<\/span>: <span class=\"hljs-literal\">true<\/span>\n  <span class=\"hljs-attr\">require_ci_green<\/span>: <span class=\"hljs-literal\">true<\/span>\n  <span class=\"hljs-attr\">hotfix_requires_ticket<\/span>: <span class=\"hljs-literal\">true<\/span>\n<span class=\"hljs-attr\">traceability<\/span>:\n  ticket_prefix: JIRA\n  <span class=\"hljs-attr\">record_propagation_to<\/span>:\n    - main<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Source attribution and legacy references<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This article is a modernized rewrite of guidance originally attributed in the source post to Laura Wingerd and Christopher Seiwald (Perforce Software). Original post: <a href=\"https:\/\/www.devopsschool.com\/blog\/best-practices-in-software-configuration-management\/\">Best Practices in Software Configuration Management<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One preserved legacy reference from the original article: <a href=\"http:\/\/www.sei.cmu.edu\/technology\/case\/scm\/tech_rep\/TR11_90\/TOC_TR11_90.html\">SEI: Spectrum of Functionality in Configuration Management Systems<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common pitfalls to avoid<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Using branches to hide unclear policy instead of writing clear policy.<\/li><li>Allowing long-lived drift between release lines and mainline.<\/li><li>Treating build scripts and toolchain metadata as optional artifacts.<\/li><li>Running infrequent big-bang merges instead of continuous propagation.<\/li><li>Keeping process documents static, hidden, or ownerless.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Strong SCM is less about tool features and more about operating discipline. This guide distills practical best practices for workspace hygiene, branching, change propagation, and reproducible builds.<\/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":4,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"predecessor-version":[{"id":78968,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions\/78968"}],"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}]}}