DevOps & CI/CD

Chapter 3
Source Control and Collaborative Development

Advance Diploma in Cloud Computing
DevOps & CI/CD   •   Advance Diploma

Source Control and Collaborative Development

Introduction

Modern software is produced by teams whose members work on shared codebases, often across locations, time zones and organisational boundaries. Source control provides the technical and organisational foundation for this work. It records changes, supports parallel development, enables review and provides evidence about who changed what, when and why. In DevOps, source control is more than a backup mechanism: it is a controlled system of record from which builds, tests, releases and infrastructure changes can be automated.

This chapter examines Git-based collaboration, including repositories, commits, branches, merging, pull requests, code review, semantic versioning, trunk-based development and GitFlow. It also considers conflict resolution, access control, repository policies and the governance risks associated with poorly managed source code.

Learning Objectives

By the end of this chapter, students should be able to:

  • explain Git’s distributed version-control model;
  • create meaningful commits and use branches safely;
  • compare merging and rebasing and resolve conflicts;
  • design pull-request and code-review workflows;
  • apply semantic versioning to releases;
  • distinguish trunk-based development from GitFlow;
  • configure permissions and repository policies;
  • evaluate source-control practices in a professional DevOps environment.

1. Git as a Distributed Version-Control System

A version-control system (VCS) stores successive states of files and metadata about their changes. Git is distributed: each clone normally contains the project’s history, branches and tags. Developers can therefore inspect history, create commits and perform many operations without network access. A remote repository, such as one hosted on GitHub, GitLab or Azure Repos, acts as a shared collaboration point rather than the sole location of history.

Git distinguishes among three important areas:

  1. Working tree: the files currently being edited.
  2. Staging area (index): the proposed contents of the next commit.
  3. Repository: the committed history stored locally or remotely.

A typical sequence is:

edit files → git add → git commit → git push

git add does not publish changes; it selects content for the next commit. git commit records a snapshot in the local repository. git push transfers local commits to a remote repository. Conversely, git fetch downloads remote history without changing the working tree, while git pull generally performs a fetch followed by integration, either by merge or rebase depending on configuration.

Git objects are identified using cryptographic object identifiers. Modern Git uses SHA-1 by default in many installations, although repositories can also use SHA-256. The identifier is a content-derived identity, not a sequential version number. A commit points to a tree representing file contents, its parent commit or parents, author and committer metadata, and a message.

Essential commands

PurposeTypical command
Copy a remote repositorygit clone URL
Inspect stategit status
View historygit log --oneline --graph
Stage a filegit add file
Create a commitgit commit -m "message"
Create or switch branchgit switch -c feature/name
Download remote referencesgit fetch origin
Publish a branchgit push -u origin branch-name
Integrate a branchgit merge branch-name
Compare changesgit diff

A commit should represent a coherent, reviewable change. Messages should explain intent, for example, Fix timeout handling in payment client, rather than updates. Small, cohesive commits improve review, rollback and fault diagnosis.

2. Branches, Merging and Rebasing

A Git branch is a movable reference to a commit. It is not an independent copy of the entire project. Creating a branch is inexpensive, which encourages developers to isolate features, fixes, experiments and release preparation.

A branch-based workflow commonly begins with an updated integration branch:

git switch main
git pull --ff-only
git switch -c feature/customer-export

The --ff-only option prevents Git from silently creating an unexpected merge commit when updating a local branch. Teams may instead use an explicit merge or rebase policy, but the policy should be understood and documented.

Merging

A merge combines histories. If the target branch has not advanced since the feature branch was created, Git may perform a fast-forward, moving the target reference to the feature tip. If both branches contain new commits, Git creates a merge commit unless the user chooses another strategy.

Merging preserves the actual branching history and is useful where auditability and explicit integration events matter. Its disadvantage is that repeated merges can produce a busy history.

Rebasing

Rebasing copies a series of commits onto a new base. The copied commits receive new identities because their parent history changes. Rebasing can create a linear history, but it rewrites commit history. Therefore, developers should not rebase shared commits unless the team explicitly permits it. Force-pushing rewritten public history can disrupt colleagues and automation.

A safe principle is: rebase private work to update it, merge or use a controlled integration method for already shared work. If force-pushing is necessary, git push --force-with-lease is safer than --force because it checks that the remote reference has not advanced unexpectedly.

Conflict resolution

A conflict occurs when Git cannot determine how to combine changes, commonly because two branches modify overlapping lines or a file is renamed and edited differently. A disciplined procedure is:

  1. identify conflicted files with git status;
  2. inspect conflict markers (<<<<<<<, =======, >>>>>>>);
  3. discuss the intended behaviour, not merely the text to retain;
  4. edit the file into the correct final state;
  5. run formatting, unit and relevant integration tests;
  6. stage the resolution with git add;
  7. complete the merge or rebase;
  8. verify the resulting diff and history.

Conflict markers must never remain in committed source. Automated tests are especially important after conflict resolution because syntactically valid code may still contain incorrect combined logic.

Git branches converging through a pull request into the main branch main feature branch review + CI commitsintegrated
Git branches converging through a pull request into the main branch
Figure: Git branches converging through a pull request into the main branch

Figure: A feature branch is tested and reviewed before integration into the main branch.

3. Pull Requests and Code Review

A pull request (PR), called a merge request in some platforms, is a formal proposal to integrate changes. It connects code, discussion, automated checks and approval records. A high-quality PR normally includes:

  • a precise title and description;
  • the problem and intended solution;
  • links to requirements or issue records;
  • tests performed and their results;
  • migration, security or operational considerations;
  • screenshots or logs where behaviour changes are visual or operational.

Code review is a socio-technical quality-control activity. Reviewers should examine correctness, maintainability, security, performance, observability, testing and compatibility. They should distinguish blocking defects from suggestions. Comments should address code and evidence rather than the character of the author.

A useful review sequence is to understand the requirement, inspect the overall design, examine implementation details, evaluate tests and check operational effects. Reviewers should avoid approving changes they have not understood. Authors should respond to every substantive comment and record decisions that future maintainers may need.

Branch protection can require successful builds, security scans, at least one or two approvals, signed commits, and an up-to-date branch before merging. “Required approval” should not be treated as a substitute for reviewer competence or automated testing.

4. Semantic Versioning and Release Identity

Semantic Versioning (SemVer) uses the form MAJOR.MINOR.PATCH, normally written as MAJOR.MINOR.PATCH. For a public API:

  • MAJOR increases for incompatible API changes;
  • MINOR increases for backward-compatible functionality;
  • PATCH increases for backward-compatible bug fixes.

For example, changing 2.4.1 to 2.5.0 indicates compatible new functionality, whereas removing a public method generally requires 3.0.0. Pre-release identifiers such as 2.5.0-rc.1 indicate a release candidate and have lower precedence than the corresponding final release. Build metadata, such as 2.5.0+build.17, may provide additional information but does not determine precedence.

SemVer depends on a clearly defined public API and honest compatibility assessment. It does not automatically describe database migrations, operational risk or every kind of deployment change. A supposedly patch-level change that invalidates stored data may be operationally major even if its code API is compatible.

Tags connect a release name to a commit. Release notes should identify changes, known limitations, migration instructions and security fixes. A reproducible release process should build from an immutable tag or commit rather than an unrecorded developer workspace.

5. Development Models

Trunk-based development

In trunk-based development, developers integrate small changes into a shared trunk, usually main, frequently. Short-lived branches may be used, but they are merged quickly. Incomplete functionality is controlled through feature flags, configuration or incremental implementation.

Advantages include reduced divergence, rapid integration feedback and a strong fit with continuous integration. Risks include unstable trunk commits if tests are weak, excessive feature-flag complexity and pressure to make changes too large for safe review. Effective trunk-based development requires automated tests, protected branches, small changes and disciplined ownership.

GitFlow

GitFlow traditionally uses a long-lived main branch for production, a develop branch for integration, feature branches, release branches and hotfix branches. It can suit scheduled releases, multiple supported versions or formal release stabilisation. However, its long-lived branches increase merge cost and delay feedback. For teams deploying continuously, GitFlow may conflict with the goal of integrating and releasing small changes frequently.

ConcernTrunk-based developmentGitFlow
Integration frequencyVery frequentOften delayed until integration or release work
Branch lifetimeUsually shortSeveral long-lived branch types
Release styleContinuous or frequentScheduled and staged
Main riskUnstable trunk or flag debtDivergence and merge complexity
Best fitContinuous deliveryControlled multi-stage releases

Neither model is universally superior. The appropriate choice depends on release cadence, regulatory controls, product architecture, team maturity and the cost of maintaining multiple versions.

6. Permissions, Policies and Governance

Repository governance combines identity, authorisation, technical controls and human accountability. Common roles include read-only users, contributors, maintainers and administrators. Least privilege means granting only the access required for a person’s responsibilities. Administrative rights should be limited and audited.

Important policies include:

  • protected default branches;
  • mandatory pull requests;
  • required status checks;
  • minimum reviewer rules and CODEOWNERS ownership;
  • prohibition of secrets in source code;
  • signed commits where identity assurance is required;
  • restrictions on force-push and branch deletion;
  • dependency and licence scanning;
  • retention and audit-log requirements;
  • documented emergency-change procedures.

Secrets must be stored in an approved secret manager, not in Git history, because deleting a file does not necessarily remove old commits from clones or caches. If a secret is committed, it should be revoked and replaced immediately; history rewriting may be useful but is not a substitute for revocation.

Governance also includes licensing and intellectual property. External code must be used according to its licence, and the organisation should track obligations for attribution, redistribution and source disclosure. Personal data should not be placed in test fixtures or commit messages without a legitimate and controlled purpose.

7. A Professional Collaborative Workflow

A practical workflow is:

  1. create or select an issue with acceptance criteria;
  2. update the local default branch;
  3. create a focused branch;
  4. implement a small change and add tests;
  5. commit with an intention-revealing message;
  6. push the branch and open a PR;
  7. allow CI to run linting, tests, security checks and build validation;
  8. respond to review and update the branch;
  9. merge using the repository’s approved strategy;
  10. delete the branch when appropriate;
  11. tag and release through an automated, auditable process.

Commit granularity should support review and rollback. Squashing can create a clean integration history, while preserving individual commits can retain detailed development evidence. The decision should be consistent with the team’s audit and debugging needs.

A useful commit message convention may include a short imperative subject and a body explaining rationale. Conventional Commits, for example, use prefixes such as feat:, fix: and docs:. Such conventions can support automated release notes, but they do not replace human assessment of compatibility.

8. Applied Case: Northstar Payments (Illustrative)

Background

Northstar Payments is an illustrative online-payment company. Its team has eight developers, deploys weekly and maintains a Java service, infrastructure code and database migration scripts. Developers currently exchange patches through chat, and the shared repository permits direct pushes to main.

Problem

A production defect was introduced when two developers independently changed timeout handling. A manual merge retained one code path but omitted a required test. The team also discovered an API key in repository history. Release numbers were informal, so consumers could not determine whether an update was compatible.

Analysis

The problems were not caused by Git alone. They resulted from absent review controls, large and overlapping changes, inadequate automated tests, weak secret governance and undefined release semantics. The company’s weekly deployment schedule also made a heavily branch-oriented release model unnecessarily slow.

Approach

Northstar adopts short-lived branches and trunk-based development. The main branch is protected: direct pushes are disabled, two approvals are required for payment-service changes, and CI must pass. CODEOWNERS assigns payment and database files to specialist reviewers. CI performs unit tests, integration tests, static analysis, dependency scanning and a reproducible build.

The exposed API key is revoked and replaced through a secret manager. Repository history is assessed and cleaned where appropriate, but revocation remains the primary control. The team adopts SemVer, publishes migration notes and tags releases from approved commits. Feature flags are used for incomplete customer-visible functionality, with owners and removal dates recorded.

Outcome

The workflow reduces unreviewed changes and makes release provenance visible. Conflicts are smaller because branches are short-lived. The team does, however, monitor feature-flag accumulation and CI duration. It retains an emergency procedure requiring post-release review and an incident record.

Learning points

The case demonstrates that collaborative development is a system of practices. Branch strategy, tests, access controls, release naming, secret management and review quality must reinforce one another. A technically correct merge can still be an organisational failure if it bypasses accountability or introduces an unsafe operational change.

9. Challenges, Limitations and Contemporary Practice

Source control does not prove that software is correct. Tests may be incomplete, reviewers may miss defects and automated scans may produce false positives. Branch protection can also become counterproductive if approval rules are excessive or reviewers approve mechanically. Teams should measure outcomes such as escaped defects, review time, change-failure rate and recovery time, while avoiding incentives that reward meaningless commit counts.

Large binary files, generated artefacts and vendor dependencies may require specialised storage or package registries. Monorepos simplify cross-component changes but can require sophisticated build selection and ownership tooling. Many repositories now integrate software bills of materials, provenance attestations and signed build artefacts to strengthen software-supply-chain assurance.

AI coding assistants can accelerate drafting and test generation, but generated code requires the same review, licence assessment, security analysis and testing as human-written code. Prompts or source fragments may expose confidential information if the tool’s data controls are not understood. AI output should be treated as an untrusted contribution, not as evidence of correctness.

Best-Practice Checklist

  • Keep the default branch protected.
  • Make changes small, coherent and testable.
  • Pull or fetch before beginning significant work.
  • Never commit secrets or personal data.
  • Use mandatory review and meaningful CI checks.
  • Prefer short-lived branches for continuously delivered systems.
  • Resolve conflicts by discussing intended behaviour.
  • Do not rewrite shared history without an agreed process.
  • Tag releases and document compatibility and migrations.
  • Audit permissions, dependencies and repository activity.
  • Review generated or AI-assisted code critically.

Chapter Summary

Git provides distributed history, inexpensive branching and controlled integration. The working tree, staging area and repository have different purposes, and commits should capture coherent intent. Merging preserves integration history, while rebasing can simplify private history but rewrites commit identities. Conflicts require both technical resolution and behavioural verification.

Pull requests combine discussion, review, automated checks and approval. Semantic Versioning communicates public API compatibility, although it does not capture every operational or data-migration risk. Trunk-based development supports frequent integration; GitFlow can support scheduled or multi-version releases but introduces longer-lived branches and greater merge cost. Repository governance requires least privilege, branch protection, secret management, licensing awareness and auditable policies. Effective collaborative development is therefore a socio-technical discipline connecting source code with quality, security, release management and organisational accountability.

Key Terms

Git: A distributed version-control system.

Repository: A directory containing versioned content and its history.

Working tree: The files currently checked out for editing.

Staging area: The proposed contents of the next commit.

Commit: A recorded snapshot with metadata and parent history.

Branch: A movable reference to a commit.

Remote: A named reference to another repository location.

Merge: Integration of two lines of development.

Rebase: Reapplication of commits onto a different base.

Conflict: A change combination Git cannot resolve automatically.

Pull request: A reviewed proposal to integrate changes.

Code review: Structured evaluation of a change by other developers.

CI: Automated validation performed when changes are integrated.

Semantic Versioning: MAJOR.MINOR.PATCH release-numbering convention.

Trunk-based development: Frequent integration into a shared main branch.

GitFlow: A branch model using feature, development, release and hotfix branches.

Branch protection: Rules restricting direct or unsafe changes.

Least privilege: Granting only the access necessary for a role.

Feature flag: A control that enables or disables functionality separately from deployment.

Repository policy: A documented technical or governance rule for repository use.

Review Questions

Short Answer Questions

  1. What are the working tree, staging area and repository in Git?
  2. Why should developers avoid rebasing commits already shared with colleagues?
  3. What is the purpose of a pull request?
  4. State the meaning of MAJOR, MINOR and PATCH in Semantic Versioning.
  5. Give two controls that can protect a default branch.

Long Answer Questions

  1. Explain Git’s distributed model and describe a complete feature-branch workflow.
  2. Compare merge and rebase, including their effects on history and collaboration.
  3. Explain how a team should resolve a source-code conflict safely.
  4. Compare trunk-based development and GitFlow, and identify suitable contexts for each.
  5. Discuss how code review, CI and repository governance work together to improve software quality.

Analytical / Application Questions

  1. A team deploys daily but maintains long-lived feature branches. Analyse the likely risks and recommend a more suitable development model.
  2. A developer accidentally commits a production credential and then deletes the file in a later commit. Identify the security implications and specify the correct response.
  3. A library adds a backward-compatible function, fixes a bug and removes an existing public function in the same release. Analyse the SemVer implications and explain what additional release information consumers need.

Multiple Choice Questions with Answers

Question 1

Which Git area contains changes selected for the next commit?

A. Working tree

B. Staging area

C. Remote repository

D. Object cache

Correct Answer: B. Staging area

Question 2

What does git fetch normally do?

A. Deletes local branches

B. Downloads remote references without integrating them into the working tree

C. Stages all modified files

D. Creates a release tag

Correct Answer: B. Downloads remote references without integrating them into the working tree

Question 3

Why is rebasing shared public commits risky?

A. It removes all file contents

B. It prevents testing

C. It rewrites commit identities and can disrupt collaborators

D. It automatically exposes secrets

Correct Answer: C. It rewrites commit identities and can disrupt collaborators

Question 4

Which action is most appropriate after manually resolving a merge conflict?

A. Commit without testing

B. Remove the repository history

C. Run relevant tests, stage the resolution and complete the merge

D. Force-push immediately

Correct Answer: C. Run relevant tests, stage the resolution and complete the merge

Question 5

Under Semantic Versioning, removing a public API function normally requires increasing which component?

A. PATCH

B. MINOR

C. Build metadata only

D. MAJOR

Correct Answer: D. MAJOR

Question 6

Which characteristic best describes trunk-based development?

A. Frequent integration into a shared trunk

B. Permanent isolation of every feature

C. A mandatory release branch for every commit

D. Direct unrestricted pushes to production

Correct Answer: A. Frequent integration into a shared trunk

Question 7

Which control most directly prevents direct unreviewed changes to main?

A. A larger local clone

B. Branch protection requiring pull requests

C. Renaming the branch

D. Deleting commit messages

Correct Answer: B. Branch protection requiring pull requests

Question 8

What is the correct primary response when a secret is committed to a repository?

A. Only delete the visible file

B. Revoke and replace the secret

C. Rename the repository

D. Add the secret to .gitignore and take no further action

Correct Answer: B. Revoke and replace the secret

Question 9

What is a principal purpose of a pull request?

A. To replace all automated tests

B. To provide a formal integration, discussion and review point

C. To encrypt every source file

D. To create a new programming language

Correct Answer: B. To provide a formal integration, discussion and review point

Question 10

Which statement about code review is most accurate?

A. Approval guarantees defect-free software

B. Review should focus only on formatting

C. Review should consider correctness, security, tests and operational effects

D. Only the original author should review the change

Correct Answer: C. Review should consider correctness, security, tests and operational effects

DevOps & CI/CD
Chapter 3 of 15