{"id":327,"date":"2026-10-13T15:11:28","date_gmt":"2026-10-13T15:11:28","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2012\/05\/23\/versioning-in-software-configuration-management\/"},"modified":"2026-10-13T15:11:29","modified_gmt":"2026-10-13T15:11:29","slug":"versioning-in-software-configuration-management","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/versioning-in-software-configuration-management\/","title":{"rendered":"SCM Versioning Done Right: Four-Part File Versions, Build Numbers, and Safer Installers"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Software versioning in <strong>Software Configuration Management (SCM)<\/strong> is the practice of assigning consistent versions to files and builds so teams can trace artifacts, reproduce releases, and avoid upgrade breakage. This guide is for build engineers, release managers, and developers who want a practical scheme they can enforce in CI and setup processes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Originally published on 2012-05-23; fully revised and updated.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This rewrite is based on guidance attributed in the original article to <em>The Build Master: Microsoft\u2019s Software Configuration Management Best Practices<\/em>. See the <a href=\"https:\/\/www.devopsschool.com\/blog\/versioning-in-software-configuration-management\/\">original post<\/a> for historical context.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"400\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2012\/05\/versioning-configuration-ma.png\" alt=\"Versioning in software configuration management\" class=\"wp-image-3798\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2012\/05\/versioning-configuration-ma.png 600w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2012\/05\/versioning-configuration-ma-300x200.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Why versioning matters in SCM<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A reliable versioning scheme helps teams answer critical questions quickly: <em>What source produced this binary?<\/em> <em>Can we rebuild that release?<\/em> <em>Is this upgrade safe?<\/em> The source material highlights these operational benefits.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Trace product binaries back to source and ownership.<\/li><li>Re-create previous builds using meaningful labels or tags.<\/li><li>Reduce component conflicts (historically called \u201cDLL hell\u201d).<\/li><li>Support setup, upgrades, and service pack workflows.<\/li><li>Help support and QA identify exactly which bits are running.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">A practical four-part file version format<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original guidance recommends a four-part file version pattern:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css language-text\"><span class=\"hljs-selector-tag\">major<\/span><span class=\"hljs-selector-class\">.minor<\/span><span class=\"hljs-selector-class\">.build<\/span><span class=\"hljs-selector-class\">.revision<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Version fields and typical ownership<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Field<\/th><th>Typically assigned by<\/th><th>How often it changes<\/th><th>Primary purpose<\/th><\/tr><\/thead><tbody><tr><td>Major<\/td><td>Component or product owner<\/td><td>Rarely during a release cycle<\/td><td>Internal product line or major release identity<\/td><\/tr><tr><td>Minor<\/td><td>Component or product owner<\/td><td>Rarely during a release cycle<\/td><td>Incremental release indicator<\/td><\/tr><tr><td>Build<\/td><td>Build or release automation<\/td><td>Every build<\/td><td>Uniquely identifies generated artifacts<\/td><\/tr><tr><td>Revision<\/td><td>Build or servicing team<\/td><td>Usually during servicing<\/td><td>Patch, hotfix, or replacement context<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Build number strategy: incremental counters vs date stamps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The source explicitly recommends a simple <strong>n = n + 1<\/strong> build number for each released build. The main reason is clarity when you have multiple releases on the same day.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Strategy<\/th><th>Example<\/th><th>Strengths<\/th><th>Weaknesses<\/th><th>Fit with source guidance<\/th><\/tr><\/thead><tbody><tr><td>Incremental counter<\/td><td>100, 101, 102<\/td><td>Simple ordering, unique per build, easy rollback discussions<\/td><td>Needs persistent counter storage<\/td><td>Recommended<\/td><\/tr><tr><td>Date-based only<\/td><td>20261013<\/td><td>Human-readable date<\/td><td>Ambiguous for multiple same-day builds<\/td><td>Not recommended<\/td><\/tr><tr><td>Date plus suffix<\/td><td>20261013.2<\/td><td>Distinguishes same-day builds<\/td><td>Convention drift and parsing inconsistency risk<\/td><td>Use only if governance is strict<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Where versioning fits in the build and release workflow<\/h2>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Code merged to main] --> B[CI starts build]\n    B --> C[Build counter increments]\n    C --> D[Artifacts get version stamp]\n    D --> E[Tests run]\n    E --> F{Release approved}\n    F -- no --> G[Fix and rebuild]\n    F -- yes --> H[Publish package]\n    H --> I[Installer compares existing versions]\n    I --> J[Upgrade only when candidate is newer]\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This flow keeps source control, build identity, and deployment behavior aligned. Without this alignment, support teams lose traceability and upgrades become risky.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example: stamping version values in CI<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following examples show a minimal pattern: persist a build counter, construct <code>major.minor.build.revision<\/code>, then stamp artifacts.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\">MAJOR=<span class=\"hljs-number\">4<\/span>\nMINOR=<span class=\"hljs-number\">2<\/span>\nPREV_BUILD=$(cat .ci\/build-counter)\nBUILD=$((PREV_BUILD + <span class=\"hljs-number\">1<\/span>))\nREVISION=<span class=\"hljs-number\">0<\/span>\n\nVERSION=<span class=\"hljs-string\">\"$MAJOR.$MINOR.$BUILD.$REVISION\"<\/span>\nprintf <span class=\"hljs-string\">\"%s\\n\"<\/span> <span class=\"hljs-string\">\"$BUILD\"<\/span> | tee .ci\/build-counter\nprintf <span class=\"hljs-string\">\"%s\\n\"<\/span> <span class=\"hljs-string\">\"$VERSION\"<\/span> | tee build\/version.txt\n\necho <span class=\"hljs-string\">\"Building version: $VERSION\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><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<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-yaml\">steps:\n  - name: Compute version\n    <span class=\"hljs-attr\">run<\/span>: .\/scripts\/compute-version.sh\n  - name: Build\n    <span class=\"hljs-attr\">run<\/span>: .\/scripts\/build.sh <span class=\"hljs-string\">\"$(cat build\/version.txt)\"<\/span>\n  - name: Publish metadata\n    <span class=\"hljs-attr\">run<\/span>: .\/scripts\/publish-metadata.sh <span class=\"hljs-string\">\"$(cat build\/version.txt)\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><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<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css language-powershell\"># <span class=\"hljs-selector-tag\">Example<\/span>: <span class=\"hljs-selector-tag\">inspect<\/span> <span class=\"hljs-selector-tag\">a<\/span> <span class=\"hljs-selector-tag\">built<\/span> <span class=\"hljs-selector-tag\">DLL<\/span> <span class=\"hljs-selector-tag\">file<\/span> <span class=\"hljs-selector-tag\">version<\/span>\n(<span class=\"hljs-selector-tag\">Get-Item<\/span> \".\\<span class=\"hljs-selector-tag\">bin<\/span>\\<span class=\"hljs-selector-tag\">MyComponent<\/span><span class=\"hljs-selector-class\">.dll<\/span>\")<span class=\"hljs-selector-class\">.VersionInfo<\/span><span class=\"hljs-selector-class\">.FileVersion<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Installer rules that reduce component conflicts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original article focuses heavily on setup behavior in Windows component ecosystems. The core principle is still useful: <strong>an installer must make deterministic, version-aware decisions<\/strong>.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Install OS-specific and locale-specific components correctly.<\/li><li>Avoid writing shared binaries into system directories unless performing an approved system-component update.<\/li><li>Do not overwrite newer components with older ones.<\/li><li>If files are in use, schedule copy on reboot to avoid mixed old\/new states.<\/li><li>Register components correctly when registration is required.<\/li><li>Keep recoverable backups of overwritten components when feasible.<\/li><li>Distribute a controlled installer package rather than loose raw component files.<\/li><li>Test setup on clean systems and on realistic machines with existing software.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices checklist<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Define one organization-wide version format and document ownership of each field.<\/li><li>Use a monotonic build counter for released builds.<\/li><li>Stamp every artifact and publish version metadata with each pipeline run.<\/li><li>Make installer overwrite logic explicitly version-aware.<\/li><li>Test upgrade and rollback paths as first-class release criteria.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Versioning in Software Configuration Management is how teams trace binaries to source, reproduce builds, and ship safer upgrades. This guide turns the original notes into a practical, modern workflow with version structure, CI stamping, and installer safeguards.<\/p>\n","protected":false},"author":1,"featured_media":3798,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[282,1122,545,244,593,397,2438,2437,2441,2440,2439,179,2435,2442,732,213,2434,2436],"class_list":["post-327","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorised","tag-configuration","tag-guide","tag-how","tag-management","tag-process","tag-scm","tag-scm-versioning-guide","tag-scm-versioning-process","tag-scm-versioning-reference","tag-scm-versioning-steps","tag-scm-versioning-tutorial","tag-software","tag-software-configuration-management","tag-software-configuration-management-versioning","tag-steps","tag-tutorial","tag-versioning","tag-versioning-in-scm"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/327","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=327"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/327\/revisions"}],"predecessor-version":[{"id":79195,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/327\/revisions\/79195"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/3798"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=327"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=327"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=327"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}