Source Control and Configuration ManagementIntroductionModern software is produced by teams, changed frequently, and deployed across several environments. Source control provides the mechanism for recording, sharing, reviewing, and recovering changes to software artefacts. Configuration management extends this discipline beyond source code to include dependencies, build definitions, infrastructure descriptions, deployment manifests, policies, and environment-specific settings. In DevOps, source control is not merely a backup system. It is a foundation for collaboration, automation, traceability, reproducibility, and controlled delivery. A well-managed repository allows a team to answer important questions: What changed? Who changed it? Why was it changed? Which version is running in production? Can the previous version be restored? Can the software be built again from a clean environment? This chapter focuses primarily on distributed version control systems (DVCS), especially the concepts commonly implemented by Git. The commands shown are illustrative; the underlying principles apply to other source-control platforms. Learning ObjectivesBy the end of this chapter, you should be able to: - explain distributed version control and repository structure;
- create meaningful commits and inspect project history;
- use branches, merges, pull requests, and code reviews safely;
- compare common branching strategies;
- apply tags and releases for traceability;
- distinguish source code, configuration, secrets, and generated artefacts;
- manage application and environment configuration securely;
- identify governance, security, and operational risks in configuration management.
1. Version Control as a DevOps CapabilityVersion control is the systematic management of changes to files over time. It supports four related capabilities: - History: a chronological record of changes.
- Collaboration: controlled concurrent work by multiple contributors.
- Recovery: restoration of known-good versions.
- Traceability: linkage between requirements, code, reviews, tests, releases, and deployments.
Source control is one part of a broader configuration-management system. Configuration management identifies important items, controls their changes, records their status, and verifies that the delivered configuration matches the approved configuration. Typical configuration items include: - application source code;
- automated tests;
- dependency manifests and lock files;
- infrastructure-as-code files;
- container and build definitions;
- deployment manifests;
- database migration scripts;
- documentation and operational runbooks;
- configuration templates and policy files.
A useful principle is that anything required to build, test, deploy, or operate a service should be versioned where practical. Generated outputs, such as temporary build directories, should normally be reproducible rather than committed. 2. Distributed Version ControlIn a centralized version-control system, the principal history is held on a central server and clients generally depend on that server for many operations. In a distributed system, each clone contains a working copy and a substantial repository history. Developers can create commits, inspect history, and create branches locally, even when temporarily disconnected from the network. A distributed repository commonly contains: - working tree: the files currently checked out;
- staging area or index: the proposed contents of the next commit;
- local repository: objects and references representing local history;
- remote repository: a shared repository used for collaboration.
The normal flow is: working tree → staging area → local commit → remote repository For example, a simplified Git workflow is: git clone https://example.org/team/catalogue.git
cd catalogue
# edit files
git status
git add src/catalogue.py
git commit -m "Validate catalogue item identifiers"
git push origin feature/identifier-validation A commit records a snapshot of selected files together with metadata such as author, timestamp, message, and parent commit. A commit is not simply a line-by-line difference; conceptually, it identifies a project state. Modern systems use content-addressed objects, so changing committed content changes its identifier. The distributed model provides flexibility, but it does not remove the need for governance. A repository still requires access controls, review rules, backup, branch protection, and policies for sensitive data. 3. Commits and Repository HistoryA good commit is: - focused on one logical change;
- internally coherent and preferably buildable or testable;
- described by a precise message;
- small enough to review;
- free of unrelated formatting or temporary files.
A weak commit such as fix stuff gives little information. A stronger message such as Reject expired access tokens during authentication states the observable purpose. Teams often use a subject line in the imperative mood, optionally followed by a body explaining context, design decisions, testing, or limitations. Commit messages should not contain passwords, tokens, private personal information, or unsupported claims. Useful inspection commands include: git status
git log --oneline --decorate --graph
git diff
git show <commit>
git blame <file> git blame can help locate the commit associated with a line, but it should be used for investigation rather than assigning personal fault. Code ownership is a team responsibility.
A commit may be amended or rewritten before publication, but rewriting history that other people already depend on can cause confusion and data loss. Shared history should generally be treated as stable. 4. Branches and Parallel DevelopmentA branch is a movable reference to a line of development. Creating a branch does not duplicate the entire repository; it creates an independent name pointing to a commit. Developers can therefore work on features, fixes, experiments, or releases without immediately changing another line of work. Typical branch names include: main or trunk: the primary integration line;feature/payment-timeout: a short-lived feature branch;bugfix/incorrect-tax-rounding: a corrective change;release/3.4: stabilization work for a release;hotfix/3.3.2: an urgent production correction.
Example: git switch -c feature/search-filter
# edit and commit
git switch main
git pull --ff-only origin main
git switch feature/search-filter
git rebase main Teams should establish whether work is merged using a merge commit, fast-forward, or rebased history. The technical choice should support traceability and should be documented rather than applied inconsistently. Common Branching Strategies| Strategy | Main idea | Strengths | Risks or limitations |
|---|
| Feature branching | Work is developed on short-lived branches and merged to the main line | Clear isolation and review boundary | Long-lived branches create integration debt | | Trunk-based development | Contributors integrate small changes frequently into a shared trunk | Rapid integration and low merge divergence | Requires strong tests, feature flags, and disciplined review | | Git Flow-style | Separate development, release, and hotfix branches | Useful for scheduled releases and multiple supported versions | More process and branch complexity | | Release branches | A release is stabilized independently while development continues | Supports parallel maintenance | Fixes must be propagated correctly across lines |
No strategy is universally best. The decision depends on release frequency, regulatory requirements, team size, test automation, and the number of supported versions. Short-lived branches are generally preferable because merge difficulty tends to increase as branches diverge in time and purpose. 5. Merging, Rebasing, and Conflict ResolutionA merge combines histories that have diverged. If the target branch has not advanced since the source branch began, a fast-forward may be possible. Otherwise, the system creates a merge result, either automatically or with human assistance. A rebase replays commits onto a different base. It can produce a linear history, but because it creates new commit identities, it should not normally be used to rewrite a shared branch. Conflicts occur when the version-control system cannot safely determine which content should prevail. A responsible conflict-resolution process is: - understand the purpose of both changes;
- inspect the conflicting files and surrounding tests;
- discuss the intended behaviour with the relevant contributors;
- edit the files deliberately and remove conflict markers;
- run formatting, unit, integration, and security checks;
- commit the resolved result and document any important decision.
Choosing “ours” or “theirs” without understanding the behaviour can silently remove a valid security or business change. Conflict resolution is therefore a design activity, not merely a text-editing task. 6. Pull Requests and Code ReviewA pull request (PR), or merge request, proposes that changes from one branch be integrated into another. It creates a structured collaboration point for discussion, automated checks, approval, and audit evidence. An effective PR should state: - the problem and intended outcome;
- the scope of the change;
- testing performed and its results;
- deployment or migration considerations;
- risks, rollback requirements, and unresolved questions.
Code review should evaluate correctness, security, maintainability, performance where relevant, observability, test quality, and compatibility. Reviewers should comment on the code and evidence rather than the person. The author remains responsible for responding to feedback and updating the change. Recommended controls include: - required reviewers for sensitive components;
- protected main branches;
- successful automated tests before merge;
- prevention of self-approval for high-risk changes;
- signed commits or verified identities where appropriate;
- review records retained for audit purposes;
- CODEOWNERS-style ownership rules.
Review is not a substitute for testing. Tests detect many executable failures; review also examines intent, architecture, threat exposure, and operational consequences. 7. Tags, Releases, and TraceabilityA tag is a named reference to a particular commit. An annotated tag can include a message, author, and signing information. Tags are useful for identifying releases, such as v2.7.0, and for connecting deployed software to an immutable source state. Semantic Versioning commonly uses the form MAJOR.MINOR.PATCH: - MAJOR: incompatible public changes;
- MINOR: backwards-compatible functionality;
- PATCH: backwards-compatible defect correction.
Semantic Versioning is a communication convention, not a guarantee. Teams must define what constitutes compatibility for their API, library, database schema, and operational interfaces. For release traceability, record the tag, build identifier, dependency lock state, configuration version, deployment time, and environment. A release should be reproducible or, at minimum, explain precisely which inputs produced it. 8. Configuration ManagementConfiguration determines how software behaves without changing its core implementation. Examples include service endpoints, feature settings, timeout values, logging levels, database connection information, and resource limits. Configuration can be classified as follows: | Category | Example | Recommended treatment |
|---|
| Non-sensitive application configuration | timeout_seconds=30 | Version-control the default or template | | Environment configuration | Production replica count | Manage through reviewed deployment configuration | | Secret configuration | Database password, API token | Store in a secret manager, not ordinary Git history | | Generated configuration | Rendered deployment file | Generate from controlled inputs where practical | | Local developer configuration | IDE or workstation settings | Keep local unless needed for team reproducibility |
The twelve-factor principle of separating configuration from code is useful, but separation does not mean lack of versioning. Non-secret configuration should usually be versioned. Secret values should not be committed; references, schemas, and safe example files may be committed. A repository might contain: config/
application.yaml # safe defaults
application.example.yaml # documented template
schema.yaml # allowed keys and types
infra/
deployment.yaml
.env.example # names only, no real secrets A production system should obtain secret values at deployment or runtime from an approved secret store. Access should follow least privilege, secrets should be rotated, and logs must avoid exposing them. Adding a secret to .gitignore is not sufficient if the secret was already committed; the history and any clones must be treated as compromised, and the credential should be revoked and replaced. Configuration validation should check required keys, data types, permitted ranges, environment-specific rules, and deprecated settings before deployment. Configuration drift occurs when the actual environment differs from the declared and approved configuration. Infrastructure as Code (IaC), immutable deployment artefacts, drift detection, and periodic reconciliation reduce this risk. 9. Configuration as Code and the Delivery PipelineConfiguration as Code expresses infrastructure, deployment, and policy in machine-readable files. It enables review, repeatability, automated validation, and rollback of configuration changes. Examples include infrastructure definitions, Kubernetes manifests, CI pipeline definitions, and policy-as-code rules. A safe pipeline commonly performs these stages: commit → lint and validate → security scan → build → test → review gate → deploy → verify The pipeline should fail safely when required configuration is missing, malformed, unauthorised, or inconsistent with policy. It should also produce evidence: commit identifier, build result, test report, artefact digest, deployment target, and approval record. Configuration should be promoted between environments deliberately. A common pattern is to build one immutable artefact and deploy that same artefact to test, staging, and production, supplying only the approved environment configuration at each stage. Rebuilding separately for each environment can produce untested differences. 10. Illustrative Case: Online Retail Checkout ServiceBackgroundAn illustrative online retailer has eight developers and deploys a checkout service several times each week. The team stores code in Git but also keeps production settings in a shared spreadsheet. Releases are made from a mixture of local branches. ProblemA production deployment used a connection-pool setting that had not been tested in staging. A developer also committed an API token to a feature branch. The token was removed in a later commit, but it remained in repository history. The team could not quickly identify the exact source version running in production. AnalysisThe organisation had source control but lacked configuration governance. The spreadsheet was not reviewed or versioned reliably, the branching process was inconsistent, and release identity was incomplete. Removing the token from the current file did not remove it from historical objects or other clones. Approach and SolutionThe team adopted short-lived feature branches and protected main. Pull requests required automated tests and review by a service owner. Each release was created from a tagged commit, and the deployment system recorded the tag and artefact digest. Safe configuration defaults and schemas were committed. Environment-specific non-secret values were managed through reviewed deployment files. Secrets moved to a managed secret store. The exposed token was revoked, replaced, and removed from accessible history using an approved history-rewriting procedure, followed by verification of all mirrors and developer clones. The pipeline added configuration linting, secret scanning, dependency scanning, and a staging deployment using the same built artefact intended for production. A rollback procedure was tested rather than merely documented. OutcomeThe team gained a reliable link between a production deployment and its source commit. Configuration changes became reviewable, secret exposure was reduced, and deployment differences were detected before release. Delivery initially slowed while controls were introduced, but recovery and investigation became substantially faster. Learning Points- Version control cannot compensate for unmanaged secrets.
- A release must identify both code and configuration inputs.
- Branching policy, review, automation, and runtime controls work together.
- Incident response must assume that committed secrets may have been copied.
11. Governance, Security, and Ethical ConsiderationsSource repositories are valuable organisational assets. Access should be based on role and least privilege, with stronger controls for deployment, identity, payment, health, and personal-data components. Audit logs should be protected from unauthorised alteration. Teams must consider privacy and data-protection obligations. Personal data, customer exports, production logs, and credentials should not be placed in repositories merely because the repository is private. Retention, deletion, access, and cross-border storage may be regulated. Software supply-chain risks include malicious dependency changes, compromised developer accounts, unsafe build actions, and tampered artefacts. Controls can include dependency pinning, lock files, provenance records, signed artefacts, isolated runners, two-person approval for sensitive changes, and continuous vulnerability monitoring. Automation and AI-assisted coding tools introduce additional concerns. Generated code may reproduce insecure patterns, introduce licensing uncertainty, or expose proprietary prompts and source material. AI-generated changes require the same review, testing, security analysis, and licensing checks as human-authored changes. An AI tool should not receive secrets or regulated data unless its use has been explicitly approved. 12. Challenges and LimitationsSource control has limits. It cannot prove that software is correct, guarantee that tests are adequate, or prevent an authorised person from making a harmful change. Large binary files may require specialised storage. Merging generated files can be difficult. A repository can become noisy when teams commit build outputs, vendor directories, local settings, or unrelated formatting changes. Branch protection can also create bottlenecks if approval rules are excessive. Conversely, weak controls allow unreviewed changes into critical systems. Policies should be risk-based: a documentation change and a payment-authorisation change need not have identical approval paths. The strongest practical approach combines small changes, automated checks, appropriate review, secure identity management, reproducible builds, clear ownership, and tested recovery procedures. Chapter SummaryDistributed version control gives each clone a rich history and enables offline work, branching, and controlled collaboration. Commits should be focused, meaningful, and traceable. Branches isolate parallel work, while merges and rebases integrate divergent histories; conflicts require understanding of intended behaviour rather than mechanical selection. Pull requests provide a formal boundary for discussion, automated validation, approval, and audit. Tags identify release states and support deployment traceability. Branching strategies should be selected according to delivery frequency, risk, team structure, and automation maturity. Configuration management extends source control to the files and settings required to build, deploy, and operate systems. Non-secret configuration should generally be versioned; secret values belong in managed secret stores. Configuration as Code, validation, drift detection, immutable artefacts, and evidence-producing pipelines improve reproducibility and safety. Governance must address access, privacy, supply-chain security, auditability, and responsible use of AI tools. Key TermsVersion control: A system for recording and managing changes to files. Distributed version control system: A version-control system in which each clone contains repository history and can support local operations. Repository: The data structure containing versioned objects, history, and references. Working tree: The files currently checked out for editing. Staging area: The proposed contents of the next commit. Commit: A recorded project snapshot with metadata and parent history. Branch: A named reference that identifies a line of development. Merge: The integration of histories from different lines of development. Rebase: Replaying commits onto a different base commit. Merge conflict: A change that requires human resolution because automatic integration is unsafe. Pull request: A proposed change accompanied by discussion, review, and automated checks. Code review: Structured evaluation of a change by one or more collaborators. Tag: A named reference to a particular commit, often used for releases. Configuration management: Controlled identification, change, recording, and verification of system configuration items. Configuration as Code: Managing infrastructure or operational configuration in machine-readable, versioned files. Secret: Sensitive information such as a password, private key, or access token. Configuration drift: Difference between approved or declared configuration and actual configuration. Infrastructure as Code: Defining infrastructure through executable or declarative configuration. Semantic Versioning: A versioning convention using major, minor, and patch components. Trunk-based development: A strategy based on frequent integration into a shared main development line. Review QuestionsShort Answer Questions- What is the difference between a working tree, staging area, and local repository?
- Why should commits normally be focused on one logical change?
- What is the purpose of a pull request?
- Why must committed secrets be revoked even after the file is deleted?
- What is configuration drift?
Long Answer Questions- Explain how distributed version control supports collaboration, recovery, and traceability.
- Compare feature branching, trunk-based development, and Git Flow-style development.
- Describe a safe process for resolving a merge conflict.
- Explain how tags, artefact identifiers, and deployment records support release management.
- Discuss how configuration as Code improves reproducibility while introducing governance responsibilities.
Analytical / Application Questions- A team maintains three long-lived branches and frequently discovers that fixes made in production are absent from the development line. Analyse the likely causes and recommend a branching and propagation policy.
- A developer commits a database password, deletes it in the next commit, and informs the team. Design the immediate incident response and the longer-term preventive controls.
- A deployment passes all application tests but fails because production uses an undocumented timeout and a different dependency version. Identify the configuration-management failures and propose pipeline controls to prevent recurrence.
Multiple Choice Questions with AnswersQuestion 1Which component contains the proposed contents of the next commit? A. Working tree B. Staging area C. Remote repository D. Release tag Correct Answer: B. Staging area Question 2What is the primary purpose of a pull request? A. To store production secrets B. To replace automated testing C. To provide a structured change, review, and validation process D. To delete repository history Correct Answer: C. To provide a structured change, review, and validation process Question 3Which practice is generally safest for a secret accidentally committed to a repository? A. Add the file to .gitignore only B. Rename the secret C. Revoke and replace the secret, then address its repository exposure D. Leave it because the repository is private Correct Answer: C. Revoke and replace the secret, then address its repository exposure Question 4What does a tag normally identify? A. A particular commit or release state B. An uncommitted working-tree file C. A reviewer’s permissions D. A temporary merge conflict Correct Answer: A. A particular commit or release state Question 5Which strategy emphasizes frequent integration into a shared main line? A. Trunk-based development B. Long-lived release branching C. Manual spreadsheet management D. Uncontrolled local development Correct Answer: A. Trunk-based development Question 6What is configuration drift? A. A deliberate code review B. A difference between declared and actual configuration C. A type of merge commit D. A semantic version number Correct Answer: B. A difference between declared and actual configuration Question 7Which item is normally appropriate to commit to a repository? A. A production password B. A private API token C. A safe configuration template containing variable names D. A customer data export Correct Answer: C. A safe configuration template containing variable names Question 8Why can rebasing a shared branch be dangerous? A. It prevents all testing B. It changes commit identities and can disrupt collaborators C. It always deletes the working tree D. It converts code into binary form Correct Answer: B. It changes commit identities and can disrupt collaborators Question 9Which control best supports reproducible promotion across environments? A. Rebuild different source versions for every environment B. Build one immutable artefact and promote it with approved configuration C. Edit production files manually after deployment D. Avoid recording deployment identifiers Correct Answer: B. Build one immutable artefact and promote it with approved configuration Question 10Which statement about code review is most accurate? A. It makes testing unnecessary B. It should focus on blame rather than behaviour C. It evaluates correctness, security, maintainability, and operational consequences D. It is required only for documentation changes Correct Answer: C. It evaluates correctness, security, maintainability, and operational consequences
|