Source control
Source control is the substrate under every other practice in this library. If the code, the infrastructure and the pipeline definitions do not live in a reviewed repository, nothing downstream can be trusted.
The standard. How Qbits selects, sets up and governs version control for a customer — repository structure, access model, review requirements and migration from a legacy system.
Selecting a version control system
Three questions decide it, in order:
- Where is the code today, and what does the team know? If the customer's team is fluent in a system and the code lives there, continuing is almost always the lower-risk choice. Migration has a cost that must be justified by a concrete benefit.
- Is the code in AWS CodeCommit? AWS no longer offers CodeCommit to new customers and recommends migration. Qbits supports migration to GitHub, including history, branches, tags and access model.
- If a new system is needed, what integrates best with the target platform? GitHub is our default: native OIDC role assumption for AWS, GitHub Actions for CI/CD, fine-grained repository permissions, and an ecosystem the customer's engineers are likely to know.
| System | Best fit | Notes |
|---|---|---|
| GitHub | Default; AWS-integrated CI/CD; large ecosystem | OIDC to AWS without long-lived keys |
| GitLab | Customer already standardised on GitLab CI | Strong built-in CI and container registry |
| Bitbucket | Customer already on Atlassian | Works well alongside Jira |
| CodeCommit | Legacy only | No longer available to new customers; migrate |
Repository setup
Every repository has:
- A meaningful name and description that states what it contains.
- A
README.mdcovering purpose, prerequisites, local setup, build and test commands, deployment process, and ownership. - A
CODEOWNERSfile naming the reviewers required for each path. - A
.gitignoreappropriate to the language and toolchain. - Branch protection on the default branch and every environment branch.
- A license statement where the repository is shared externally.
Structure
Application repository:
.
├── src/ # application source
├── tests/ # unit, integration, contract tests
├── docs/ # architecture, decisions, runbooks
├── infra/ # Terraform or other IaC
├── ansible/ # configuration management, where used
├── scripts/ # build and operational scripts
├── .github/ # workflows and composite actions
└── README.md
Infrastructure repository:
.
├── modules/ # reusable modules
├── environment/ # per-environment variable files
├── src/ # scripts and referenced files
├── docs/
└── README.md
Pre-commit hooks
Hooks run before code reaches review, so reviewers spend their time on design rather than formatting.
| Hook | Purpose |
|---|---|
terraform fmt / language formatter | Consistent formatting |
| Linter | Language-specific static checks |
| Secret scanning | Prevents credentials reaching the remote |
terraform validate | Configuration validity |
| Commit message lint | Enforces the ticket prefix convention |
Hooks are installed by a setup script in the repository, not by asking each engineer to configure their machine.
Access model
- Repository access is granted through teams, not individuals.
- Default branch is protected: no direct pushes, no force pushes, no deletion.
- Required reviews: at least one, and two for infrastructure or security-sensitive paths.
- Required status checks: build, tests, static analysis, secret scan.
- Signed commits where the customer requires them.
- Deploy keys and personal access tokens are avoided in favour of short-lived OIDC credentials.
Migrating from CodeCommit
Inventory List repositories, branches, tags, size and current access grants. Identify anything unusual — large binaries, submodules, LFS.
Mirror Clone as a mirror and push to the target with all refs, preserving history and tags.
Recreate access Map existing IAM-based access to team membership in the target system.
Recreate automation Rebuild CodePipeline, CodeBuild and webhook integrations as GitHub Actions or the target's CI.
Cut over Make the old repository read-only, update local remotes, and keep it available for reference for a defined period before archival.
Verify Confirm commit count, branch list, tag list and a sample build from the new repository before decommissioning.
Evidence
- Repository list with purpose and owner.
- Branch protection configuration export.
- Sample pull request showing review and passing checks.
- Pre-commit configuration in the repository.
- Migration record where applicable.