Skip to content

Git Standards & Commit Conventions

Status: 🟢 Active  |  Owner: Engineering Enablement  |  Last Reviewed: 2025-Q4


Overview

Consistent git hygiene is the foundation of a navigable project history. Good commit messages make it possible to understand why a change was made months later, to generate meaningful changelogs, and to efficiently bisect bugs. These standards apply to every repository in the organisation.


Required Git Configuration

All engineers must configure git with their full name and organisational email address. These are verified by the pre-commit hook framework.

git config --global user.name "Your Full Name"
git config --global user.email "[email protected]"
git config --global core.autocrlf false     # Never convert line endings
git config --global core.eol lf             # Always use LF
git config --global pull.rebase true        # Rebase on pull, never merge
git config --global push.default current   # Push current branch by default
git config --global init.defaultBranch main

Commit Message Format: Conventional Commits

All commits must follow the Conventional Commits specification. This format is enforced by a commitlint pre-commit hook.

Format

<type>(<scope>): <short summary>

[optional body]

[optional footer(s)]

Rules

  • Subject line: Maximum 72 characters. Imperative mood ("add feature", not "added feature" or "adds feature"). No period at the end.
  • Body: Optional. Wrap at 72 characters. Explain what and why, not how.
  • Footer: Used for breaking change notices and issue references.

Allowed Types

Type When to Use
feat A new feature (triggers MINOR version bump)
fix A bug fix (triggers PATCH version bump)
docs Documentation changes only
style Formatting, whitespace — no logic change
refactor Code restructuring without feature change or bug fix
perf Performance improvement
test Adding or updating tests
chore Build process, dependency updates, CI configuration
ci CI/CD configuration changes
revert Reverts a previous commit

Breaking Changes

Breaking changes are indicated by: 1. BREAKING CHANGE: in the footer, OR 2. ! after the type/scope: feat(api)!: remove deprecated v1 endpoints

Both trigger a MAJOR version bump in automated release tooling.

Examples

feat(orders): add discount code validation

Validate discount codes against the promotions service before applying
them to an order. Invalid or expired codes now return a 422 with a
descriptive error message.

Closes PROJ-1234

---

fix(payments): prevent double-charge on network timeout

When the payment provider returns a timeout, we were retrying without
checking for idempotency, causing duplicate charges. Added idempotency
key to all payment requests.

Fixes PROJ-5678

---

feat(api)!: remove deprecated v1 order endpoints

The /api/v1/orders endpoints deprecated in v2.3.0 have been removed.
All consumers must migrate to /api/v2/orders before upgrading.

BREAKING CHANGE: /api/v1/orders/* endpoints removed. Migrate to /api/v2/orders/*.

---

chore: upgrade Spring Boot to 3.2.4

Includes security fixes for CVE-2024-XXXXX.

Commit Discipline

Atomic Commits

Each commit represents a single, complete, logical change. A commit should be deployable on its own — it should not leave the system in a partially broken state.

  • ✅ Good: "fix: correct VAT calculation for EU orders"
  • ❌ Bad: "WIP", "temp", "fix tests", "misc changes"

What Not to Commit

  • Secrets: API keys, passwords, tokens — use the secrets manager. Gitleaks pre-commit hook blocks secret commits.
  • Build artefacts: .jar, .class, .pyc, node_modules/, dist/ — add to .gitignore.
  • IDE configuration: .idea/, .vscode/ (with exceptions for shared workspace settings) — add to .gitignore.
  • OS files: .DS_Store, Thumbs.db — add to global .gitignore.
  • Commented-out code: Delete it. The history has it.

Commit Size

Keep commits small and focused. A commit that changes 20 files across 5 different concerns will be impossible to review or revert cleanly. If you find yourself writing "and" in a commit message, consider splitting the commit.


Signed Commits

All commits to main (and all PR commits) must be GPG or SSH signed. See Signed Commits Policy for setup instructions.

GitHub enforces this via branch protection rules — unsigned commits cannot be merged to protected branches.


Interactive Rebase Before PR

Before opening a pull request, clean up your commit history with interactive rebase: - Squash "fix tests" and "WIP" commits into the logical commits they belong to. - Ensure each commit in the PR is atomic and has a proper conventional commit message. - Rebase onto the latest main to avoid merge conflicts.

# Interactively rebase the last 4 commits
git rebase -i HEAD~4

# Rebase onto latest main
git fetch origin && git rebase origin/main

References


Last reviewed: 2025-Q4  |  Owner: Engineering Enablement