Prerequisite: You should be familiar with basic Git operations and understand the Monorepo Architecture of our codebase.

Overview

Tuturuuu follows standardized conventions for Git commits and branch naming to improve collaboration, automate releases, and maintain a clean, navigable repository history. We use two main specifications:

  1. Conventional Commits for structured commit messages
  2. Conventional Branch for consistent branch naming

These conventions help automate our CI/CD workflows, generate changelogs, and make our development process more efficient.

Conventional Commits

What are Conventional Commits?

Conventional Commits is a specification for adding human and machine-readable meaning to commit messages. It provides a set of rules for creating an explicit commit history, making it easier to write automated tools on top of.

The basic structure of a conventional commit is:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Types

Tuturuuu uses the following commit types:

TypeDescriptionExample
featNew feature or enhancementfeat: add dark mode support
fixBug fixfix: prevent crash when user data is undefined
docsDocumentation changesdocs: update installation instructions
styleCode style changes (formatting, no code change)style: format code with prettier
refactorCode refactoringrefactor: simplify authentication logic
perfPerformance improvementsperf: optimize database queries
testAdd or fix teststest: add unit tests for auth middleware
buildChanges affecting build system or dependenciesbuild: update dependency to fix security issue
ciChanges to CI configuration files and scriptsci: add workflow for staging deployments
choreRoutine tasks, maintenancechore: update package.json metadata

Scopes

Scopes provide additional context about which part of the codebase is affected. In our monorepo structure, we often use package or app names as scopes:

feat(web): add new dashboard layout
fix(ui): correct button alignment in mobile view
chore(types): update supabase database types

Breaking Changes

Breaking changes must be indicated by adding a ! after the type/scope or by using a BREAKING CHANGE: footer:

feat(api)!: require authentication for all endpoints

BREAKING CHANGE: All API endpoints now require authentication tokens.

Examples

Here are some examples of conventional commits used in our codebase:

feat(web): add new calendar integration
fix(supabase): correct permission issue in auth policy
docs(readme): update development setup instructions
style: apply consistent formatting with prettier
refactor(utils): simplify date formatting functions
perf(queries): optimize workspace user loading
test(auth): add tests for token verification
build(deps): update Next.js to v14
ci(vercel): add automatic preview deployments
chore(release): publish packages

Conventional Branches

What are Conventional Branches?

Conventional Branch refers to a structured naming convention for Git branches that makes it easier to identify branches by type and purpose.

The basic structure is:

<type>/<description>

Branch Types

Tuturuuu uses the following branch types:

TypeDescriptionExample
mainMain development branchmain
featureFor new featuresfeature/user-dashboard
bugfixFor bug fixesbugfix/login-error
hotfixFor urgent fixeshotfix/security-vulnerability
releaseFor preparing releasesrelease/v1.2.0
choreFor maintenance taskschore/update-dependencies

Naming Rules

  1. Use lowercase alphanumeric characters and hyphens
  2. Keep names concise but descriptive
  3. Include ticket/issue numbers when applicable
  4. Avoid special characters (except hyphens)

Examples

feature/workspace-sharing
bugfix/file-upload-error
hotfix/auth-vulnerability
release/v2.5.0
chore/update-react-18
feature/issue-123-user-profile

How These Conventions Improve Our Workflow

1. Automated Changelog Generation

Our conventional commits are used to automatically generate changelogs for releases. Different commit types are categorized accordingly:

# Changelog

## Features

- add dark mode support (#123)
- add calendar integration (#124)

## Bug Fixes

- prevent crash when user data is undefined (#125)

## Documentation

- update installation instructions (#126)

2. Semantic Versioning

Conventional commits help determine the next semantic version for packages:

  • fix: commits trigger a PATCH increment (1.0.0 → 1.0.1)
  • feat: commits trigger a MINOR increment (1.0.0 → 1.1.0)
  • Commits with BREAKING CHANGE trigger a MAJOR increment (1.0.0 → 2.0.0)

3. Automated Package Publishing

In our CI workflows, package publishing is automatically triggered when a PR with specific commit types is merged. For example, our release-types-package.yaml workflow triggers when:

on:
  pull_request:
    types: [closed]
    paths:
      - 'packages/types/package.json'
  # ...

jobs:
  check-version-bump:
    if: github.event.pull_request.merged == true && contains(github.event.pull_request.title, 'chore(@tuturuuu/types)')
    # ...

4. Better Code Reviews

With conventional commits and branches, it’s easier to understand the purpose of a pull request at a glance:

  • A PR from feature/user-dashboard with commits like feat: add user stats widget clearly indicates a new feature
  • A PR from bugfix/auth-issue with commits like fix: prevent token expiration error indicates a bug fix

5. Simplifying Navigation

Conventional branch names make it easier to navigate the repository history and find specific changes. For example:

# Find all feature branches
git branch --list "feature/*"

# Find branches related to authentication
git branch --list "*auth*"

Tools and Enforcement

We use a dedicated CI/CD check to enforce our Git conventions:

Branch Naming Check

We use a GitHub Action workflow to verify that branch names follow our convention:

name: Branch Name Check

on:
  push:
    branches-ignore:
      - main
      - production

jobs:
  check-branch-name:
    name: Check branch name
    runs-on: ubuntu-latest
    steps:
      - name: Check branch name
        run: |
          BRANCH_NAME=${GITHUB_REF#refs/heads/}
          if ! [[ $BRANCH_NAME =~ ^(feature|bugfix|hotfix|release|chore)/.+ ]]; then
            echo "❌ Branch name '$BRANCH_NAME' doesn't follow the conventional branch format."
            echo "Branch name should be in format: type/description"
            echo "Allowed types: feature, bugfix, hotfix, release, chore"
            exit 1
          else
            echo "✅ Branch name follows convention: $BRANCH_NAME"
          fi

Best Practices

Writing Good Commit Messages

  1. Use the imperative mood (“add” not “added” or “adds”)
  2. Capitalize the first letter of the description
  3. Do not end the description with a period
  4. Keep the description under 72 characters
  5. Use the body to explain the what and why, not the how

Example of a well-formatted commit:

feat(auth): Add multi-factor authentication support

Implement TOTP-based multi-factor authentication to improve security.
The implementation follows the RFC 6238 standard.

Closes #123

Branch Management

  1. Create branches from the latest main branch
  2. Keep branches focused on a single task or issue
  3. Regularly rebase long-lived branches on main to avoid merge conflicts
  4. Delete branches after they’ve been merged

Pull Request Workflow

  1. Create a branch with the appropriate type based on the work
  2. Make commits using conventional commit messages
  3. Push the branch and create a pull request
  4. Use conventional commit style for the PR title
  5. After approval and merge, delete the branch

Conclusion

Following these Git conventions helps us maintain a clean, understandable repository history, automate release processes, and improve collaboration across the team. By standardizing both commit messages and branch names, we create a more efficient development workflow.

For more information, refer to the official documentation for Conventional Commits and Conventional Branch.