jongkwan.dev
Development · Essay №051

Code Review and Commit Conventions

A practical guide to effective code review culture, Conventional Commits, and semantic versioning

Jongkwan Lee2026년 2월 20일11 min read
Contents

Commit conventions make automated versioning possible; code review makes bug prevention and knowledge sharing possible.

Code review and commit conventions are the practices that determine a team's code quality and collaboration efficiency. A systematic commit message convention enables automated versioning and releases. Effective code review prevents bugs before they ship and raises the technical level of the team. As of 2026, AI-based code review tools are spreading quickly and reshaping review culture along with them.

Conventional Commits

Specification

Conventional Commits is a specification that imposes a structured format on commit messages. It lets automated tooling analyze commit history and handle versioning, changelogs, and releases without human input.

Format

text
<type>[optional scope]: <description>
 
[optional body]
 
[optional footer(s)]

Commit types

TypeDescriptionSemVer impact
feat:New featureMINOR bump
fix:Bug fixPATCH bump
docs:Documentation changeNone
style:Code formatting (semicolons, indentation, etc.)None
refactor:Code improvement with no behavior changeNone
perf:Performance improvementPATCH bump
test:Adding or fixing testsNone
build:Build system change (Webpack, npm, etc.)None
ci:CI configuration changeNone
chore:Other changes (tooling config, package updates, etc.)None
revert:Reverting a previous commitDepends on the case

Breaking changes

text
feat(auth)!: change token format to JWT v5
 
BREAKING CHANGE: Token format changed from HS256 to ES256.
All existing tokens will be invalidated.
Migration guide: docs/migration/token-v5.md
  • Append ! after the type, or add a BREAKING CHANGE: footer
  • Triggers a MAJOR version bump

Real-world examples

bash
# new feature
feat(payment): add cryptocurrency payment support
 
Implement Bitcoin and Ethereum payment processing
using CoinGate API integration.
 
Closes #234
 
# bug fix
fix(auth): resolve JWT refresh token race condition
 
Multiple concurrent refresh requests could generate
duplicate tokens. Added mutex lock to token refresh handler.
 
Fixes #567
 
# refactoring
refactor(order): extract validation logic to separate service
 
Move order validation from OrderController to
OrderValidationService for better testability and reuse.
 
# performance
perf(query): optimize user search with database index
 
Add composite index on (email, created_at) to users table.
Query time reduced from 450ms to 12ms for 1M records.

Semantic Versioning (SemVer)

Format

A version has three parts, MAJOR.MINOR.PATCH, and each part indicates the compatibility level of the change.

PartMeaningTriggerExample 2.4.1
MAJORBackward-incompatible changeBREAKING CHANGE2 (second major)
MINORBackward-compatible feature additionfeat:4 (fourth minor)
PATCHBackward-compatible bug fixfix:1 (first patch)

Bump rules

Kind of changeCommit typeVersion changeExample
Bug fixfix:PATCH bump1.0.0 -> 1.0.1
New featurefeat:MINOR bump1.0.1 -> 1.1.0
Breaking changeBREAKING CHANGEMAJOR bump1.1.0 -> 2.0.0

Pre-release versions

text
1.0.0-alpha.1     <- alpha
1.0.0-beta.1      <- beta
1.0.0-rc.1        <- release candidate
1.0.0             <- general availability

Version ranges in npm and Maven

json
{
  "dependencies": {
    "express": "^4.18.0",  // 4.x.x (MINOR and PATCH updates allowed)
    "lodash": "~4.17.0",   // 4.17.x (PATCH updates only)
    "react": "18.2.0"      // exactly this version
  }
}

Automated changelogs and releases

semantic-release

A tool that analyzes commit history and decides the version, generates the changelog, and publishes the release automatically.

text
analyze commit history
    |
    +-- feat: -> MINOR bump
    +-- fix: -> PATCH bump
    +-- BREAKING CHANGE -> MAJOR bump
    |
    v
update version in package.json
    |
    v
generate CHANGELOG.md
    |
    v
create Git tag (v2.1.0)
    |
    v
create GitHub Release
    |
    v
publish package to npm/PyPI/etc.

CI/CD pipeline integration

yaml
# GitHub Actions example
name: Release
on:
  push:
    branches: [main]
 
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # full history required
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npm test
      - run: npx semantic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Example of a generated CHANGELOG

markdown
# Changelog
 
## [2.1.0] - 2026-02-10
 
### Features
- **payment**: add cryptocurrency payment support (#234)
- **auth**: implement OAuth 2.1 PKCE flow (#245)
 
### Bug Fixes
- **auth**: resolve JWT refresh token race condition (#567)
- **order**: fix decimal precision in total calculation (#571)
 
### Performance
- **query**: optimize user search with database index (#580)

Notable tools

ToolLanguageCharacteristics
semantic-releaseNode.jsMost mature, rich plugin ecosystem
release-please (Google)Multi-languageMonorepo support, Release PR model
standard-versionNode.jsManually triggered
commitizenNode.jsInteractive commit message authoring
convcoRustFast execution, Conventional Commits validation

Pre-commit hooks

Definition

A mechanism that runs code checks automatically before a Git commit is created, guaranteeing a baseline of quality.

Husky + lint-staged setup

bash
# install
npm install --save-dev husky lint-staged
 
# initialize Husky
npx husky init
json
// package.json
{
  "lint-staged": {
    "*.{ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{json,md}": [
      "prettier --write"
    ],
    "*.test.{ts,tsx}": [
      "jest --bail --findRelatedTests"
    ]
  }
}
bash
# .husky/pre-commit
npx lint-staged

commitlint (commit message validation)

bash
# install
npm install --save-dev @commitlint/cli @commitlint/config-conventional
javascript
// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor',
      'perf', 'test', 'build', 'ci', 'chore', 'revert'
    ]],
    'subject-max-length': [2, 'always', 72],
    'body-max-line-length': [2, 'always', 100]
  }
};
bash
# .husky/commit-msg
npx --no -- commitlint --edit $1

Execution flow

The CODEOWNERS file

Definition

A mechanism that declares code owners per directory or file in a repository so that reviewers are assigned automatically when a PR is opened.

Example configuration

text
# .github/CODEOWNERS
 
# global default owners
* @team-lead @senior-dev
 
# owners per service
/services/auth-service/    @auth-team
/services/payment-service/ @payment-team @security-team
/services/notification/    @platform-team
 
# infrastructure code
/infrastructure/           @devops-team
/terraform/                @devops-team @security-team
/.github/                  @devops-team
 
# security-sensitive files
/services/*/security/      @security-team
*.env.example              @security-team
 
# shared libraries
/packages/shared-utils/    @platform-team
/packages/api-client/      @api-team
 
# documentation
/docs/                     @tech-writer @team-lead

CODEOWNERS best practices

  1. Assign teams, not people: mention teams rather than individuals (@org/team-name)
  2. Mandatory review on security files: assign security-team to security-related directories
  3. Overlapping coverage: have multiple teams review critical areas
  4. Regular updates: refresh CODEOWNERS whenever team structure changes
  5. Tie into branch protection: enable "Require review from CODEOWNERS"

Code review best practices

Based on Google's engineering practices

Google's code review guide is the most widely referenced set of practices in the industry.

From the reviewer's side

PrincipleDescription
Review promptlyWithin 24 hours of the PR opening (within hours if possible)
Constructive feedbackPoint out the problem, propose an alternative, explain why
Rank by importanceMUST (blocking), SHOULD (strongly recommended), COULD (optional)
Focus on the codeTalk about the code, not the person
Understand the contextRead the PR description, linked issues, and design docs

From the author's side

PrincipleDescription
Small PRs200-400 lines recommended, 800 lines maximum
Self-reviewReview your own PR once before submitting
Adequate explanationPR title, body, screenshots, test plan
Single purposeOne PR, one purpose (do not mix)
Tests includedTest code for the change is mandatory

PR template

markdown
## Summary
<!-- summary of the change (1-3 sentences) -->
 
## Motivation
<!-- why is this change needed? (link the related issue) -->
 
## Changes
<!-- list of major changes -->
 
## Test Plan
<!-- how it was tested and the results -->
 
## Screenshots
<!-- screenshots if the UI changed -->
 
## Checklist

Levels of review feedback

LevelTagMeaningExample
Blocker[MUST]Cannot merge until resolvedSQL injection vulnerability
Major[SHOULD]Strongly recommended but open to discussionProposing a more efficient algorithm
Minor[COULD]Optional improvementBetter variable name, added comment
Praise[NICE]Recognition of well-written code"This abstraction is very clean"
Question[Q]Question for understanding"What is the intent of this logic?"

The current tool landscape

As of 2026, AI-based code review tools are expanding past traditional static analysis toward system-level understanding.

ToolCharacteristicsMain features
GitHub Copilot Code ReviewGitHub native, automatic PR reviewCode quality, security, performance analysis
Qodo (formerly CodiumAI)Test generation plus reviewTest coverage analysis, edge case detection
CodeRabbitPR summary plus line-by-line reviewDependency analysis, security vulnerabilities
SourceryPython-specificRefactoring suggestions, code quality score
CodeAnt AIBackend API-specificAPI contract validation, N+1 query detection
Amazon CodeGuruAWS nativeIntegrated runtime performance analysis

What AI review does well, and where it falls short

Strengths

  • Automatic bug detection: null pointers, resource leaks, race conditions found automatically
  • Security vulnerability scanning: SQL injection, XSS, authentication bypass, and more
  • Code quality improvements: suggestions on duplication, complexity, and naming
  • Faster reviews: AI handles the mechanical pass so humans concentrate on design and business logic

Limits and cautions

The Veracode 2025 GenAI Code Security Report measured over 100 large language models and found that 45% of AI-generated code failed security tests. CodeRabbit's State of AI vs Human Code Generation Report (2025, analyzing 470 pull requests) found cross-site scripting (XSS) vulnerabilities 2.74 times more often and logic or correctness errors 1.75 times more often than in human-written code.

LimitMitigation
Weak grasp of business logicHuman review by a domain expert is mandatory
False positivesConfigure override rules and use them as training signal
Shallow architecture-level analysisImproving through 2026 (system-aware agents)
Incomplete security validationRun alongside a dedicated security reviewer

A hybrid AI plus human review strategy

Signed commits

Why signing matters

Git's author and committer fields can be set to anything by anyone. A signed commit cryptographically proves that the commit really was written by that person.

GPG signing

bash
# generate a GPG key
gpg --full-generate-key
 
# list keys
gpg --list-secret-keys --keyid-format=long
 
# configure the GPG key in Git
git config --global user.signingkey ABC123DEF456
git config --global commit.gpgsign true
 
# signed commit
git commit -S -m "feat: add secure payment"
 
# verify the signature
git log --show-signature
bash
# sign with an SSH key (simpler than GPG)
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
 
# signed commit (automatic)
git commit -m "feat: add secure payment"

GitHub vigilant mode

A GitHub feature that marks unsigned commits as "Unverified" to flag the possibility of tampering.

The full automation pipeline

The end-to-end flow from commit to release:

Summary

Commit conventions standardize the message format, and that is the starting point for automating version decisions and changelogs. semantic-release and pre-commit hooks wire that format into the build and release pipeline so humans intervene less. Code review assigns accountability through CODEOWNERS and separates feedback into MUST/SHOULD/COULD, aiming at bug prevention and knowledge sharing at the same time. The current practical arrangement gives AI the mechanical pass while humans concentrate on business logic and architecture. Read alongside the branching strategy covered earlier in this series, the path from commit to deployment fits into a single picture.